인프런 커뮤니티 질문&답변

한울님의 프로필 이미지
한울

작성한 질문수

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문

포인터 기초 #2

포인터 및 기타 궁금증

해결된 질문

작성

·

360

0

루키스님 안녕하세요

다름이 아니라,

포인터를 공부하다가 헷갈리는 부분들이 있습니다...

__int64* ptr2 = &number;에서

number의 값이 int type인데 그 주소는 __int64 type으로 받아들이고 있어서 오류가 난다고 하셨는데 &numbernumber의 타입이 다른 게 왜 오류의 원인인지 모르겠습니다...;;

그리고 __int64 type으로 가정하고 받아들이고 있는 것은 &number 내에 있는 number의 값 아닌가요?

 

p.s. 요즘 알고리즘 문제들을 기초적인 것들부터 풀고 있는데

cincout을 사용할 때

std::ios_base::sync_with_stdio(false);

cin.tie(NULL);

추가 + endl‘\n’으로 변경해야 통과가 되는 문제들이 있었습니다..(1개만 해도 되는 문제들도 있었지만)

 

그래서 해당 내용들을 한 번 인터넷으로 검색해봤는데

std::ios_base::sync_with_stdio(false);

cin.tie(NULL);

이 코드들의 경우

아직 지식이 부족해서 그런지 대략적으로 알고리즘 풀이용으로는 사용가능하지만 실제 업무에서 사용하려면 부작용이 큰 방법정도로만 이해를 했습니다.

 

실제 업무에서 사용하는데 부작용이 크다면 사용을 안 하는 게 맞는 것 같은데

사용을 안 한다면 printf, scanf에 비해서 cin, cout의 실행시간이 느려져버린다고 하니,

그렇게 된다면 실제 업무에서는 cin,cout 대신 printf, scanf 등만 사용이 되는 것인가요?

그리고 endl‘\n’도 비슷한 경우인가요?

답변 4

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

1.

number == 특정 메모리의 주소값

개념적으로 틀린 말은 아니지만, number == 주소값이라고 외우면
포인터랑 헷갈리기 쉽습니다.
[알아서 해당 메모리에 무엇인가를 꺼내고 저장해준다]

혹은 [상자에 이름을 지어준다]라고 이해하는게 좋습니다.

변수의 주소값 == 변수

변수의 주소값 == 변수라기 보다는
포인터 타입의 변수가 [주소를 저장하는 변수]에 가깝습니다.

포인터의 의미 == '주소값을 저장하는 변수'
YES
== '변수를 저장하는 변수'
NO (가령 주소없음을 의미하는 NULL은 변수가 아니죠)

2. 메모리 주소값에 type에 있는 것은 아니고
당연히 그냥 하나의 정수에 불과합니다. (ex. 100, 200, 300)
포인터는 단순 주소가 아니라 여기에다 추가로
[해당 주소를 타고 가면 무엇이 있는지]를 같이 내포합니다.
int* : 주소는 주소인데 타고 가면 int가 있음
char* : 주소는 주소인데 타고 가면 char가 있음

void* : 주소는 주소인데 타고 가면 뭐가 있는지는 모르겠으니 너가 나중에 바꿔 써

이런식이죠.

 

한울님의 프로필 이미지
한울
질문자

감사합니다!
포인터가 조금 헷갈리긴 하네요...ㅠㅠㅠ

한울님의 프로필 이미지
한울
질문자

1가지만 더 여쭤보고 싶습니다.

number == 주소값이 일단 개념상으로 맞긴 하다면

&number도 number의 주소값을 반환해주는데 

&number와 number는 차이가 어떻게 되나요?

Rookiss님의 프로필 이미지
Rookiss
지식공유자

그래서 그렇게 [number == 주소값]으로 생각하기 보단
[바구니를 지칭하는 또 다른 별칭]으로 생각하라는겁니다.
코드가 컴파일 되면 힙이나 스택 영역의 상대 주소로 치환되어
그 안에 있는 데이터를 갖고 오거나 해당 주소에 쓰거나~
하게 되겠지만 그건 어디까지나  로우 레벨 관점에서
[바구니를 찾기 위한] 연산이지 주소가 핵심은 아닙니다.
(스택 영역이라면 고정 주소가 아니라 스택 ebp 기준으로 한 상대 주소이기도 하고요)

반면 &number는 정말 찐!으로 해당 변수의 주소를 갖고 오고
이를 포인터에 대입할 때는 타입까지 일치해야 하며
문법을 일일히 이해하고 외우려하기 보단 그냥
하다 보면서 에러를 만나고 고치다보면 자연스럽게 알게 되는 부분이 많습니다.

한울님의 프로필 이미지
한울
질문자

그렇군요..감사합니다!

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

그렇다면 주소를 뽑아오는 &number가 int*으로 변환?반환?(둘 중 뭐가 맞는지 모르겠습니다...)된다면__int64* ptr2 = int* 로 되는 것인가요?

네 그런 느낌입니다. 근데 int64* 와 int*는 엄연히 다르니 문제가 일어나는거죠.

두번째는 질문이 이해가 안가는데
내용을 보니 변수명을 '실제 저장되는 무엇인가'로 오해하는 것 같네요.
변수명은 말 그대로 C++에서만 사용하고 실제 컴파일 되면 존재하는 개념이 아니고
실제 주소 (스택 주소, 힙 주소, etc..)로 치환되어 코드가 만들어집니다.
결과적으로 number는 0x138A3FEF를 우리가 이해할 수 있는 이름으로 부른 것이고
그 안에는 1이 들어있는게 맞겠죠.

한울님의 프로필 이미지
한울
질문자

앗 그렇다면 제가 아무래도 &number의 기능을 심각하게 오해했던 것 같은데

1.

number == 특정 메모리의 주소값

1 == 특정 메모리에 저장된 값

변수의 주소값 == 변수

포인터의 의미 == '주소값을 저장하는 변수' == '변수를 저장하는 변수'

가 되는 것인가요?

2.

메모리 주소값에도 type이 붙을 수가 있나요?

 

 

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

1.
네 &number를 하면 그 기본적으로 (number의 타입)* 형태입니다.
궁금하면 auto v = &number;로 입력하고 auto가 무엇으로 추론되었는지 살펴보면 됩니다.

2.
아닙니다. 포인터에는 주소값만 저장이 되고,
실제 값은 '그 주소'로 순간이동해야 있습니다.

3.
그냥 단순하게 생각해서 비트 연산은 다르게 생각해야 하고
&를 and라고 생각하면 안 됩니다.
flag &= (1 << 2); 이렇게 하면 1<<2 즉 0b100 랑 &를 하는데,
비트 연산에서 1이 아닌 값은 다 0으로 밀어버리기 때문에 아예 다른 의미가 됩니다.

한울님의 프로필 이미지
한울
질문자

그렇다면 주소를 뽑아오는 &number가 int*으로 변환?반환?(둘 중 뭐가 맞는지 모르겠습니다...)된다면

__int64* ptr2 = int* 로 되는 것인가요?

해석이 더 어렵습니다...ㅠㅠㅠ

+

앗 그게...특정 메모리의 주소값 안이라는 뜻이 포인터가 아니라

int number = 1;

int* ptr = &number;

디버깅했을 때 나오는

0x138a3fef     00000001의 경우처럼

0x138a3fef이라는 메모리주소값 안에 들어있는 내용들을 의미한 것이었습니다

그 안에는 변수와 그 변수의 실제값(number,1)이 둘 다 저장된 것이 맞을까요?

포인터의 경우라면 &ptr이라는 메모리주소값 안에 (ptr과 &number)가 저장된 것이 맞을까요?

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

ddddddd

 

number의 값이 int type인데 그 주소는 __int64 type으로 받아들이고 있어서 오류가 난다고 하셨는데 &numbernumber의 타입이 다른 게 왜 오류의 원인인지 모르겠습니다...;;

말 그대로 거짓말이기 때문이죠. (실제 값은 int인데 int64라고 주장하고 있기 때문)
__int64*의 경우 단순하게 생각해 int64 데이터를 가리키는 포인터입니다.
말로 풀어 쓰면 [주소값인데, 그 주소 값을 타고 가면 int64가 있을꺼야!]라는 의미입니다.
실제로 데이터를 타고 갔을 때 정말 int64가 있는지는 나중의 문제지만..
일단 문법상으로 int 변수의 주소값을
아무렇지 않게 int64 포인터로 참조하는 것은 실수 방지 차원에서 막아준겁니다.

그리고 __int64 type으로 가정하고 받아들이고 있는 것은 &number 내에 있는 number의 값 아닌가요?

둘다입니다. &number를 하면 number가 int이고 그 주소값을 얻어왔으니
자연스럽게 int*이 됩니다. int64*에다 넣고 싶으면 변환을 해주거나,
실제 int64 데이터를 갖고 와야죠.

그리고 알고리즘 문제는 통과만 되면 되고
어차피 '실무'에서는 어차피 콘솔 로그를 찍을 일이 거의 없어 잊고 살아도 됩니다.

한울님의 프로필 이미지
한울
질문자

1. int 타입 변수의 주소를 저장하는 포인터의 타입은 무조건 int*인 것은 규칙인가요?

죄송합니다 포인터 이해가 자꾸 헷갈려서...ㅠㅠㅠ

2.

특정 메모리의 주소값 안에는 변수이름이랑 변수의 실제값이 모두 저장된다고 봐도 될까요?

3. 

그리고 bitflag 부분에서

flag = (1 << 3);로 무적상태를 만든 뒤

변이상태 추가를 위해(무적+변이)

flag |= (1 << 2);를 해주셨는데

bitmask 계산을 위해서는 |가 사용하는 게 맞다고 생각은 들지만

한편으로는

무적 + 변이이면 무적 and 변이로

flag &= (1 << 2)가 되어야하지 않나?라며 머릿속에서 충돌이 자꾸 발생하고 있습니다..;;

한울님의 프로필 이미지
한울

작성한 질문수

질문하기