기타 지식

C++) 포인터를 알아보자.

주의) 이건 초보자 강좌가 아닙니다. C / C++의 함수 부분까지 이해한 사람이 읽기를 추천드립니다.

 

안녕 개붕이들아

오늘은 C++ 기초중에 가장 같은걸로 유명한걸 알아보자 ㅎㅎ

(참고로 C에서도 같은 원리이기 때문에 포인터가 어려우면 읽어보는걸 추천해)

 

바로 포인터야.

영어로는 Pointer 라고 하는데

2021-02-09 23_20_12.png

사전에 있는것처럼 무언가를 가리키는걸 뜻해.

근데 뭘 가리키는걸까..?

 

바로 변수의 주소야.

주소가 뭔 소리냐고?

 

이 변수는 메모리 (RAM) 라는 공간에 저장돼.

이 메모리 공간에는 각각 번호가 붙어있고,

이 번호가 바로 변수의 주소값이야.

 

사진으로 쉽게 설명해보자.

2021-02-09 23_42_23.png

이게 우리의 램 공간이야.

여기에 int age = 34;

라는 명령어가 실행되면 무슨 일이 일어날까?

 

컴퓨터는 여기서, 자동으로 램에 빈 공간을 찾아.

그 다음에 그 빈 공간에다가 34라는 값을 저장하는 거지.

2021-02-09 23_51_12.png

봐바!

우리의 똑똑한 친구 컴퓨터가 0x01 ~ 0x04에 34라는 값을 저장했어!

age = 53; 같은 명령을 실행시켜주면 저 34라는 값이 53이라는 값으로 바뀌는거야!

(여기서 age 변수가 메모리 공간을 4개나 차지한 이유는, int 자료형의 크기가 4바이트여서 그래.)

 

그럼 포인터는 뭘까?

포인터 변수는 바로 주소값을 저장할 수 있는 변수야.

일단 예시로 한번 알아보자.

int* pointer = &age;

일반적인 변수 선언같았는데, 자료형 뒤에 별이 붙어있지?

이렇게 별을 자료형 뒤에 붙이고 변수 이름을 적어주면 포인터 변수가 생성돼.

즉,

가리키고_싶은_자료형* 변수이름;

형식이야.

 

그럼 이 변수에 넣고있는 값인 &age는 뭘까?

&는 레퍼런스 라고 불러.

 

2021-02-10 00_03_00.png

사전에서 말하는 것 처럼, 참조라는 뜻이야.

근데 참조한다는게 뭔 소리냐고?

 

정말 간단해.

레퍼런스(&) 기호를 변수 이름 앞에 붙이면 그 변수의 주소값을 알려주는거야.

예를 들어서 std::cout << &age << std::endl; 이라는 명령어를 실행하면,

age의 주소값인 0x01 이 출력되겠지.

std::cout << age << std::endl; 을 했을 때 34라는 age 변수에 저장된 값이 출력되는거랑은 다르게 출력되는게 보이지..?

 

그럼 이 포인터 변수는 메모리에 어떻게 저장되는걸까?

int *pointer = &age; 를 실행 했을때의 메모리 상태를 한번 보자.

2021-02-10 00_01_25.png

봐바!!

우리의 메모리 공간에 새로운 변수가 생겼어.

0x05 ~ 0x08 위치에 새로운 값이 들어갔네!

포인터 변수는 바로 특정 변수의 주소값을 저장하고 있는 변수라는거지.

 

그럼 이 포인터를 어따가 쓰는걸까?

한번 응용해볼게.

 

int age = 65;

int* p = &age;

 

std::cout << p << std::endl;

std::cout << *p << std::endl;

 

어라? 마지막 std::cout 명령어에서 출력하는 변수가 이상하지 않아?

포인터 변수 이름 앞에 * 을 붙여놨잖아?!

 

일단 출력해보자.

2021-02-10 00_20_20.png

????

std::cout << p << std::endl; 에서는 012FFB84 라는 값이 출력되고,

std::cout << *p << std::endl; 에서는 65라는 값이 출력됐네??

 

아하, 즉 포인터 변수인 p를 그대로 출력하면 포인터 변수가 가리키고 있는 주소가 출력되고,

포인터 변수인 p 앞에 별 (*) 을 붙인 상태로 출력하면 포인터 변수가 가리키고 있는 주소에 있는 변수의 값이 나오는구나!

 

그럼 실험을 조금 해보자!

 

int age = 65;

int* p = &age;

 

std::cout << "age : " << age << std::endl;

std::cout << "p : " << *p << std::endl;

 

age = 34;

 

std::cout << "age : " << age << std::endl;

std::cout << "p : " << *p << std::endl;

 

처음 age 변수에 65라는 값을 넣어주고,

age 와 *p 의 값을 각각 출력해준 다음,

age 변수에 34라는 값을 넣어주고,

다시 age 와 *p 의 값을 출력하는 코드야.

실행해보면...

2021-02-10 00_28_00.png

우와!

age 의 값이 변함과 동시에 *p 의 값도 변했어!

왜냐고? p 는 포인터 변수고, 이 p는 age의 위치를 가리키고 있거든,

즉 age 의 값이 아닌 위치를 가리키고 있기 때문에, age가 변하면 *p 의 값도 변하는거야!

 

그럼 또 다른 실험을 해보자!

 

int age = 65;

int* p = &age;

 

std::cout << "age : " << age << std::endl;

std::cout << "p : " << *p << std::endl;

 

*p  = 34;

 

std::cout << "age : " << age << std::endl;

std::cout << "p : " << *p << std::endl;

 

이렇게 하면 어떻게 될까??

이번에는 age 의 값을 바꾼게 아니라, *p 의 값을 바꿔봤어,

한번 보자.

 

2021-02-10 00_30_39.png

오!! 이번에도 값이 변했어!

여기서 알 수 있는건 바로,

*p = 34; 는 즉, p가 가리키고 있는 메모리 주소에 있는 값을 바꾸는거지!

그러기 때문에 age 랑 *p 랑 같은 값이 나오는거고!

 

근데 이걸 어디에 써먹냐고?

엄청 좋은 예시로 함수가 있어.

 

주의) 이 예시는 조금 어려우니 이해가 안되면 그냥 건너뛰고 그 밑에 있는 예시를 읽어보세요.

예를 들어서 "23:37:54" 라는 문자열을 시간, , 로 잘라서 변수 3개에 넣는 함수를 만들어보자.

 

void cutTime(std::string time, int* hour, int* minute, int* second) {

    *hour = std::stoi(time.substr(0, 2));

    *minute = std::stoi(time.substr(3, 2));

    *second = std::stoi(time.substr(6, 2));

}

 

어라 오류뜬다고?

당연하지! std::stoi 함수는 iostream 에 없거든!

#include <string>#include <iostream> 아래에 적어주자!

 

여기서 알아갈게 조금 있는데,

time.substr() 은 std::string 변수에 기본적으로 있는 기능이야.

.substr(위치, 크기);

형식으로 사용하고, 문자열의 위치 위치에 크기 만큼 문자열을 잘라내는 기능을 해.

그래서 substr(0, 2) 해준거지 (0위치에 2길이의 문자열을 잘라서 return)

 

어쨌든, 이걸 실행해보자.

 

int main(int argc, char* argv[]) {

    int hour;
    int minute;
    int second;

 

    cutTime("23:37:54", &hour, &minute, &second);

 

    std::cout << hour << std::endl;
    std::cout << minute << std::endl;
    std::cout << second << std::endl;

 

    return 0;

}

함수를 위에 선언해줬으니, 저렇게 main 문에 적어주면 실행되겠지?

각 변수들에 무슨 값이 들어갔는지도 알아야하니깐, 마지막에 저렇게 출력문도 적어보자.

 

이 상태로 실행하면?!

2021-02-10 00_52_36.png

오오 23:37:54 라는 문자열이 23, 37, 54 라는 각각의 숫자로 나뉘어서 hour, minute, second 변수에 각각 들어갔어!

 

근데 뭔가 예시가 어려우니 좀 더 쉬운 예시를 들고와볼게.

 

이번에는 함수에 값이 들어가있는 int 변수를 넣으면 그 변수가 두배가 되도록 해보고 싶어.

해보자.

 

void doubleInt(int* num) {

    *num = *num * 2;

 

이제 main 문에

 

int a = 34;

doubleInt(&a);

std::cout << a << std::endl;

 

넣고 실행해보면...

2021-02-10 00_56_52.png

34의 두배인 68이 변수 a에 저장되어서 나왔어!

어떤식으로 작동된건지 뜯어보자!

 

int a = 34; <- 여기서 a 라는 변수를 만들고 34라는 값을 넣어줬어.

doubleInt(&a); <- 이제 doubleInt 라는 함수를 실행 해주는거야, doubleInt 함수는 int 형 포인터 변수를 필요로 하니깐 a의 주소값을 보내줬어.

 

void doubleInt(int* num) { <- doubleNum 함수의 포인터 변수인 num 에 a의 주소값이 도착했어!

    *num = *num * 2; <- 이 주소값이 가리키고 있는 변수(a) 의 값을 2 곱해서 넣어줘.

 

std::cout << a << std::endl; <- 이제 출력이야!

 

어때..? 이해 좀 됐어..?

나도 포인터라는 개념이 이해도 잘 안되고 어따 써먹는지도 영 모르겠어서 익히기가 엄청 어려웠었는데,

이거라도 읽고 좀 이해했으면 좋겠다.

 

궁금한 점이나 어려운점, 수정 바라는 부분이나 오류 있는 부분은 댓글로 달아줘!

읽어줘서 고마워

104개의 댓글

2021.02.10
@쿄코

아니면 포인터 설명했으니까 파이썬의 변수 특징 설명해보는건 어때

난 파이썬 변수가 재밌더라구

1
2021.02.10
@망했떼

어딜 드러운 구렁이를 대려와!!

신성한 C++을 해야지 쯧쯧

 

1
2021.02.10
@쿄코

힝 ㅠㅠ

그럼 gcc랑 gpp 차이점좀 알려줘

왜 gpp로 c언어 컴파일이 되는거야

0
2021.02.10
@망했떼

gcc - GNU

gpp - ATOM (MIT LICENSE)

 

C에서 가능한건 전부 C++에서 가능해서 cpp 컴파일러에서 C가 돌아가는거야.

C에다가 괴상한것들 추가한게 C++이거든..

0
2021.02.10
@쿄코

으으으으으디 신성한 C 앞에서 클라스 따위를 들이밀어!!

0
2021.02.10
@망했떼

그리고 하스켈을 팔아먹는것이지

0
2021.02.10
@멍청이

다음은 올리디버거를 이용한 디스 어셈블링으로...(?)

0
2021.02.10
@쿄코

아이다 프로 써달라고 ㅋㅋㅋㅋ

0
2021.02.10
@망했떼

아 아이다 디자인 구려 ㅋㅋㅋㅋㅋ

0
2021.02.10
@쿄코

아이다 디컴파일러 최고라구

0
2021.02.10

끝까지 연재해 주십시오 휴먼

혹시 책 추천 가능하십니까 인강이나 유튜버나 C++은 너무 없어오

0
2021.02.10
@섭탱

열혈 C++

0
2021.02.10
@섭탱

열혈 C++ 사놓고 안일었어

난 책이랑은 안맞더라...

 

C는 학원에서 기초정도만 배웠고,

C++ 은 C랑 비슷해서 독학으로 가능했음..

0
2021.02.10
@섭탱

Effective c++, more effective c++

Stl 도서 찾아보시고

 

Modern c++ 책 보시고

0
2021.02.10
@섭탱

그냥 아무 기본서 하나 읽고 그 다음이 C++ 기초플러스, 그 다음이 이펙티브 C++

0
2021.02.10

뭔말인지 알겠당 ㅎㅎ

0
2021.02.10
@바보똥개
0
2021.02.10
@쿄코

스크립트 언어쓰는데

c++공부할꺼얏 히히

0
2021.02.10
@바보똥개

"오늘도 사탄 한명이 일을 잃었습니다."

0
2021.02.10

근데 배열 설명 없이 포인터만 달랑 설명하면 나중에 배열 얘기할 때 헷갈려하지 않게서?

0
2021.02.10

아니 왜 고생길에 들어올려고 하는거야? 하지마 하지마...

C/C++에 익숙해지면 다른 프로그래밍 언어 속 터져서 못써

0
2021.02.10
@이스F91

어셈블리 : 나 불렀어?

0
2021.02.10
@이스F91

뭔 말도 안되는소리냐, C/C++ 10년 넘게 했지만 개발 속도에서 1년 한 C# 에 반도 안나온다. 절반 나오면 빠른거다. 보통 10~20% 수준.

 

그냥 C/C++ 가 필요한 영역들이 있다.

0
2021.02.10
@댜기

오~10년 넘게 했으면 알건 알겠네.

이 분야에서 그런사람 요즘 좀처럼 찾기 어렵던데 반가워.

내가 얘기하고 싶었던건 포인터 덮어쓰기 같은걸 통해서 struct -> struct 변환 같은건 어지간한 언어에서는 찾기 힘들어서 한 얘기였음.

거기에 함수포인터를 통해서 run time에 실행 모듈을 바꿔치기 하고....뭐뭐, 그런것들 말이지.

그런거 쓰다보면 다른 언어는 전문 같은거 파싱할때 속터지더라.

C#은 가끔 테스트용 클라이언트를 만드느라고 쓰는데 생산성은 좋은데 답답한 면이 많더라고.

여튼, 말을 너무 짧게 했나 싶은데.... 댓글에 줄줄줄 길게 쓸 수 없잖아?

0
2021.02.11
@이스F91

다른언어엔 없는 c++기능이란건 대부분 다른 언어를 c++의 사고방식에 갖혀서 생각해서 그럼

 

 

0
2021.02.10

메모리 시작 주소가 0x00이 아니라 0x01이라 굉장히 불편함

0
2021.02.10
@gogogog

ㅋㅋㅋㅋㅋㅋㅋ

사실 컴퓨터 메모리처럼 4바이트로 하려고 했는데 그러니 너무 길어지더라..

0
2021.02.10

Int는 왜 4byte 일까? 요것부터가 중요하다.

0
2021.02.11
@살애기

거야 int를 만들고 정의할땐 32bit cpu였으니깐

0
2021.02.13
@보라돌이얌

근데 16비트 시절에는 int가 2바이트였엉

0
2021.02.13
@살애기

으엉?

0
2021.02.13
@보라돌이얌

16bit시절엔 주소값이 크기가 2바이트 32bit시절엔 4바이트이고 그게 int의 값이 되고...

또 cpu의 비트수만큼 변수의 크기를 정하는게 효율적이고

0
2021.02.13
@살애기

아아..... 이제야 알겠군

첫 댓글이 의문이 아니었구나

난 첫 댓글이 물어보는건지 알았음

0
2021.02.10

응 러스트나 고 할거야~ 틀따라라딱딱언어 안쓸거야

0
2021.02.10
@잠적자

생각만 하고 가라 글 싸지르고 가지 말고

0
2021.02.10

포인터 이해 못 했으면 초보자 강의가 맞음

0
[삭제 되었습니다]
2021.02.10
@지옥에서몸부림쳐라

포인터 변수는 값을 담는 변수가 아니라, 값을 담는 변수의 위치를 담는 변수야.

가장 많이 사용하는 경우가, 내가 예시로 든 것 처럼 한 변수를 다른 함수에서도 값을 바꾸거나 하도록 짜는 경우가 있거든,

예를 들어 두 수의 합과 차를 두 변수에 나눠서 저장하는 함수가 있다고 하면,

void sumdif(int a, int b, int* sum, int* dif) {

*sum = a + b;

*dif = a - b;

}

 

이렇게 짜주는거지.

그러면,

int sum, dif;

sumdif(5, 3, &sum, &dif);

 

이리 해줬을때,

변수 sum에는 8이 들어가고, 변수 dif에는 2가 들어가지!

0
2021.02.11
@지옥에서몸부림쳐라

사용법에 대한 쉬운 예시는 아웃풋을 2개이상 받고싶을때 쓰는것

0
2021.02.11
@승냥

참고로 tuple 쓰면 가능함

 

auto func() {

return tuple(30, 53, 11);

}

 

int a, b, c;

auto[a, b, c] = func();

0
2021.02.11
@쿄코

오우쉣 c++에는 그런게 있네 c만 하다보니...

0

야 설명 잘한다 재밌네

0

히히ㅣㅎhtml 짱 javascript 짱 완벽한 언어 html

0
2021.02.10
@크립토커런시트레이더

Please

0
2021.02.10
@크립토커런시트레이더

이쯤되면 컴고수

0
2021.02.10

자 이제 포인터을 했으니 클래스와 객체지향 자료구조까지 해주세요!

0

망할 포인터... 모든 구조체와 배열 클래스가 이것 땜에 난이도 제곱됨.

0
2021.02.10
@레게강같은붐업

구조체는 왜?

0
mas
2021.02.10

착한 컴공과 1학년은 자바와 파이썬이나 준비하러 갑시다

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜
5248 [기타 지식] 페미니즘은 여성에게 도움이 되었는가 01 18 키룰루 18 1 일 전
5247 [기타 지식] 아무리 만들어봐도 맛이 없는 칵테일, 브롱스편 - 바텐더 개... 3 지나가는김개붕 2 6 일 전
5246 [기타 지식] 일본에 의해서 만들어진 칵테일들 편 - 바텐더 개붕이의 술 ... 2 지나가는김개붕 6 8 일 전
5245 [기타 지식] 중국에서 안드로이드 폰을 사면 안되는 이유? 10 대한민국이탈리아 24 9 일 전
5244 [기타 지식] 최근 지각변동이 일어나는 국내 항공업계 (수정판) 15 K1A1 23 11 일 전
5243 [기타 지식] 도카이촌 방사능 누출사고 실제 영상 21 ASI 2 16 일 전
5242 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 지구 2부 21 Mtrap 8 16 일 전
5241 [기타 지식] 100년을 시간을 넘어서 유행한 칵테일, 사제락편 - 바텐더 개... 5 지나가는김개붕 1 18 일 전
5240 [기타 지식] 오이...좋아하세요? 오이 칵테일 아이리쉬 메이드편 - 바텐더... 3 지나가는김개붕 2 20 일 전
5239 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 지구 1부 31 Mtrap 13 19 일 전
5238 [기타 지식] 칵테일의 근본, 올드 패션드편 - 바텐더 개붕이의 술 이야기 15 지나가는김개붕 14 20 일 전
5237 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 인류 2부 22 Mtrap 14 20 일 전
5236 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 인류 1부 13 Mtrap 20 20 일 전
5235 [기타 지식] 서부 개척시대에 만들어진 칵테일, 카우보이 그리고 프레리 ... 3 지나가는김개붕 6 25 일 전
5234 [기타 지식] 모던 클래식의 현재를 제시한 칵테일편 - 바텐더 개붕이의 술... 4 지나가는김개붕 2 26 일 전
5233 [기타 지식] 브라질에서 이 칵테일을 다른 술로 만들면 불법이다, 카이피... 5 지나가는김개붕 1 28 일 전
5232 [기타 지식] 럼, 라임, 설탕 그리고 다이키리 편 - 바텐더 개붕이의 술 이... 2 지나가는김개붕 6 28 일 전
5231 [기타 지식] 1999년 도카이촌 방사능누출사고 대량 방사능 피폭 피해자들 ... 9 ASI 5 29 일 전
5230 [기타 지식] 진짜 레시피는 아무도 모르는 칵테일 싱가포르 슬링편 - 바텐... 3 지나가는김개붕 2 29 일 전
5229 [기타 지식] 통계로 보는 연애 상황에서 외모의 중요성 8 개드립에서가장긴... 11 2024.04.04