인디안 보호구역

[C/C++] 포인터에 대한 질문 -1 본문

Study/언어 공부하는 인디안

[C/C++] 포인터에 대한 질문 -1

Indie-An 2015. 7. 24. 17:44




1.  포인터에서 rvalue 자료형과 lvalue 자료형의 허용규격



위의 소스코드를 보면서 의문을 가지게 됐다.

pointer 변수는 어떤 자료형이든간에 일반적으로 4bytes이다. (64bit 운영체제에서는 8bytes)

포인터 변수는 변수의 값을 저장하는 것이 아니라 메모리의 주소를 저장하는 공간이라 크기가 같은 것이다.


그렇다면 lvalue가 포인터변수일 때,

굳이 이렇게 rvalue를 lvalue와 똑같은 (int *)형으로 변환해주지 않아도 되는거 아닌가?

근데 형변환 안하면 컴파일 에러난다.

이렇게 말이다.


컴파일러는 위와 같은 코드를 아래와 같은 이유에서 오류로 취급하고 있다.



1>------ Build started: Project: 2015_Summer, Configuration: Debug Win32 ------
1>  PointerType.cpp
1>c:\users\admin\documents\visual studio 2013\projects\2015_summer\pointertype.cpp(9): error C2440: '=' : cannot convert from 'double *' to 'int *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>c:\users\admin\documents\visual studio 2013\projects\2015_summer\pointertype.cpp(10): error C2440: '=' : cannot convert from 'int' to 'int *'
1>          Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>c:\users\admin\documents\visual studio 2013\projects\2015_summer\pointertype.cpp(11): error C2440: 'type cast' : cannot convert from 'double *' to 'double'
1>          There is no context in which this conversion is possible
1>c:\users\admin\documents\visual studio 2013\projects\2015_summer\pointertype.cpp(12): error C2440: '=' : cannot convert from 'double *' to 'int *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


1) pi = &d;

2) pi = (int)&d;

3) pi = (double)&d;

4) pi = (double *)&d;


1) int형 포인터변수(int *)인 pi에 double형 변수의 주소를 넣으려 하고있다.

 당연히 에러나지! 왜냐면 int형 변수는 4bytes이고 double형 변수는 8bytes다.

 pi는 int형 포인터 변수이고, int형 포인터변수(int *)는 가리키는 대상체를 4bytes만큼만 읽을텐데,

 double형 변수가 들어있는 주소를 대입해버리면 그 주소로 찾아간 뒤, - - - - | - - - - 이렇게 반쯤(8bytes 중 4bytes만) 읽히잖아.

 그리고 int형 변수는 32비트 중, 맨 앞을 부호로 삼고, 나머지 비트는 실제 값으로 처리를 하는데

 double형 변수는 64비트 중에도, 부호, 정수, 가수, 이렇게 여러 부분 나뉘는데 값을 읽는 과정에서도 오류날 것이 분명하다.


책(혼자 연구하는 C/C++)에서 포인터의 타입에 관해 설명이 나와있다.


"... 포인터 변수를 선언할 때는 가리키고자 하는 대상체의 타입을 반드시 명시해야 한다.

대상체의 타입을 포인터의 타입이라고 한다.

... 포인터가 타입을 가져야 하는 이유는 다음 두 가지 이다.

첫번째 이유는 *연산자로 포인터의 대상체를 읽거나 쓸 때 대상체의 바이트 수와 비트 해석 방법을 알아야 하기 때문이다...

... 두 번째 이유는 인접한 다른 대상체로 이동할 때 이동 거리를 알기 위해서이다...."



3) double형을 double형으로 형변환 하려고 하니까 오류가 났다. ㅋㅋ


4) 1번이랑 비슷하다. int형 포인터 변수에 double형 포인터 변수(double *)로 캐스팅된 d의 주소를 넣으려 하고있다.

 다시 말해, 좌측은 int형 변수의 주소를 받고, 그 주소를 찾아가서 4바이트만큼을 읽으며, 첫번째 비트는 부호를 결정하고, 나머지 비트는 값을 결정할 준비를 하고 있는데,

 우측은 double형 변수의 주소를 받으므로, 그 주소를 찾아가서 4바이트만큼 읽는다 한들 정보가 다를 뿐더러, 좌측이 int*인데 우측은 double*이므로 형이 맞지 않는다.



2) 근데 나는 2번을 잘 모르겠는게, pi는 int형 포인터 변수이므로 자료형은 int* 이다.

 그런데 자료형이 int*인 pi에 대입되는 변수는 i인데, i의 자료형은 int이다.

 맞지 않나? 일반적으로

int *pi;

int i;

pi = &i;

이렇게 i의 주소를 넣는데, 좌측 pi는 int*형, 우측 i는 int형이잖아.

그러니까 pi = (int)&d; 는 비트해석이 올바르진 않을지언정 연산할 때의 자료형은 올바르다. 라는 결과가 나올줄 알았다.

안나오니까 내가 틀린건데, 잘 모르겠다.

잘하는 사람들한테 물어보고난 뒤에, 추가로 글 수정해야지.




2. 결론


어쨌든 결론적으로,

pi = (int *)&d;

는 컴파일은 되지만 엉뚱한 값이 나온다. 그건 좌측 값과 우측 값의 자료형이 맞지 않았기 때문이고,

좌측은 int*형인데 반해, 우측은 double형 데이터를 억지로 int*형으로 변환한 것이였기 때문이다.

int*형 포인터변수는 int형 변수의 주소만을 받아야 한다.

끝.



Comments