int main() { const int test = 0; int* p_test = (int*)&test;
*p_test += 1;
printf("%d\n", test); printf("%d\n", *p_test);
return 0; } 해당코드를 실행하면 컴파일 에러가 뜨는게 아니라 0,1이 출력됩니다. 혹시나 싶어서 포인터의 값과 정수변수의 주소값을 확인해보니 일치하였습니다. 어떻게 이런게 가능한 것인가요?
C 인지, CPP 인지?
CPP입니다.
CPP 에서는 C 와 달리 test 값의 storage 가 생성되지 않을 수도 있습니다.
즉, 출력된 0는 storage 에 담긴 값이 아니고, 컴파일러의 constant table 에서 나온 값이 아닐까 생각되는데 저 경우가 다른 컴파일러에서도 나올지는 모르겠네요.
CPP에서는 CONST값은 실제 메모리공간에 할당되지 않는다는 말씀인가요?
위 경우와 같이 주소를 참조한다던가, 다른 파일에서 extern 으로 선언되어 있는 경우 등을 제외하고는 메모리 영역이 할당되지 않습니다. 그런데 저 경우는 storage 가 잡혀 있으니 에러가 나올 것 같은데 이상하네요.
포인터 형변환 시키면 뭐든지 다 되지 않나요? 데이터영역에 들어가는 건0이지 test가 아니니까 일단 컴파일은 문제가 없을테구요. 다만 test가 0으로 나온건 컴파일러 최적화가 아닐까 합니다.
씨ㅍㅍ에서는 포인터 형변환도 제약이 많습니다. 포인터를 보이드형으로 바꾸었다가 다른 걸로 바꾸는 것도 잘 안됩니다.
gcc와 g++ 기준에서
두개다 컴파일러에서 에러또는 워닝을 도출하지 않았습니다. gcc에서는 1,1 g++에서는 0,1 로 결과를 도출하였습니다.
C에서의 결과는 납득이 갑니다. 일단 const 변수의 메모리가 할당되고 이후 얼마든지 포인터 형변환으로 바꿀수 있기 때문에 값이 변경될 수 있죠.
그냥 제 생각이라서 이게 정답이다 라고 단언하긴 어렵습니다만 얘기해 보자면...
const int test = 0; 이라는 코드를 오해하고 있는게 아닌가 싶습니다. 그러니까
const char *msg = "Hello World"; 와 같이 생각해서 msg의 값을 못바꾸지 않겠냐고 예상했지만 그와 달랐다고 의문을 가지는게 아닌가 싶은데
첨부터 그 코드는 const char msg[] = "Hello World"; 와 같은 소스라서 msg의 값을 바꾼다는게 별로 이상한거 같지 않습니다.
왜 C++ 에선
... printf("%d\n", test); ...
... printf("%d\n", 0); ...
위의 코드에서 int의 선언에 static으로 선언하니 메모리 침입 오류가 뜹니다. 뒤적거려보니 static const로 선언하면 메모리 DATA영역에 잡히는 것이 아닌 상수영역에 잡혀서 그렇다고 하는데 Const 지역변수의 경우에는 stack영역이 아닌 다른부분에 메모리가 잡히는 걸까요?
질문이 두 곳에 있어서 여기도 답변 달아봅니다.
확장자가 *.c 이냐 *.cpp(*.cc) 이냐에 따라 다른 결과가 나옵니다.
유사한 질문을 올린 사람도 있고 어셈블리 레벨에서 답변해 주신분도 있네요. 아래 링크 참조하시면 도움이 될 것 같습니다.
http://www.daniweb.com/software-development/cpp/threads/53814
C에서는 실제로 메모리의 값을 읽어와서 데이터 레지스터의 값을 출력하는데 mov edx, DWORD PTR _a$[ebp] push edx C++에서는 그냥 상수 10을 출력해버리네요 push 10 ; 0000000aH
재미있네요 ㅎㅎ 만약 저변수가 함수포인터 였다면 어떻게 될지 생각해보는 것도 재미있겠네요
텍스트 포맷에 대한 자세한 정보
<code>
<blockcode>
<apache>
<applescript>
<autoconf>
<awk>
<bash>
<c>
<cpp>
<css>
<diff>
<drupal5>
<drupal6>
<gdb>
<html>
<html5>
<java>
<javascript>
<ldif>
<lua>
<make>
<mysql>
<perl>
<perl6>
<php>
<pgsql>
<proftpd>
<python>
<reg>
<spec>
<ruby>
<foo>
[foo]
C 인지, CPP 인지?
C 인지, CPP 인지?
C와 CPP에서 잡히는 메모리 영역이 다른가요?
CPP입니다.
CPP 에서는 C 와 달리 test 값의
CPP 에서는 C 와 달리 test 값의 storage 가 생성되지 않을 수도 있습니다.
즉, 출력된 0는 storage 에 담긴 값이 아니고, 컴파일러의 constant table 에서 나온 값이 아닐까 생각되는데 저 경우가 다른 컴파일러에서도 나올지는 모르겠네요.
CPP에서는 해당 CONST값이 Data영역에 잡히지 않는다는 말씀인가요?
CPP에서는 CONST값은 실제 메모리공간에 할당되지 않는다는 말씀인가요?
위 경우와 같이 주소를 참조한다던가, 다른 파일에서
위 경우와 같이 주소를 참조한다던가, 다른 파일에서 extern 으로 선언되어 있는 경우 등을 제외하고는 메모리 영역이 할당되지 않습니다.
그런데 저 경우는 storage 가 잡혀 있으니 에러가 나올 것 같은데 이상하네요.
포인터 형변환 시키면 뭐든지 다 되지 않나요?
포인터 형변환 시키면 뭐든지 다 되지 않나요?
데이터영역에 들어가는 건0이지 test가 아니니까 일단 컴파일은 문제가 없을테구요.
다만 test가 0으로 나온건 컴파일러 최적화가 아닐까 합니다.
씨ㅍㅍ에서는 포인터 형변환도 제약이
씨ㅍㅍ에서는 포인터 형변환도 제약이 많습니다.
포인터를 보이드형으로 바꾸었다가 다른 걸로 바꾸는 것도 잘 안됩니다.
C와 CPP 컴파일러의 결과가 달라지는 군요
gcc와 g++ 기준에서
두개다 컴파일러에서 에러또는 워닝을 도출하지 않았습니다.
gcc에서는 1,1
g++에서는 0,1
로 결과를 도출하였습니다.
C에서의 결과는 납득이 갑니다. 일단 const
C에서의 결과는 납득이 갑니다.
일단 const 변수의 메모리가 할당되고 이후 얼마든지 포인터 형변환으로 바꿀수 있기 때문에 값이 변경될 수 있죠.
그냥 제 생각이라서 이게 정답이다 라고 단언하긴
그냥 제 생각이라서 이게 정답이다 라고 단언하긴 어렵습니다만 얘기해 보자면...
const int test = 0;
이라는 코드를 오해하고 있는게 아닌가 싶습니다.
그러니까
const char *msg = "Hello World";
와 같이 생각해서 msg의 값을 못바꾸지 않겠냐고 예상했지만 그와 달랐다고 의문을 가지는게 아닌가 싶은데
첨부터 그 코드는
const char msg[] = "Hello World";
와 같은 소스라서 msg의 값을 바꾼다는게 별로 이상한거 같지 않습니다.
왜 C++ 에선 ... printf("%d\n",
왜 C++ 에선
를
처럼 컴파일러가 해석하는 지 궁금해하는 것 같습니다.
최적화오류가 아니냐고 의심하는 분도 이걸 말씀하시는거고요.
volatile 키워드면 증명이 되겠죠.
CPP 컴파일러는 재미있군요
위의 코드에서 int의 선언에 static으로 선언하니 메모리 침입 오류가 뜹니다.
뒤적거려보니 static const로 선언하면 메모리 DATA영역에 잡히는 것이 아닌 상수영역에 잡혀서 그렇다고 하는데
Const 지역변수의 경우에는 stack영역이 아닌 다른부분에 메모리가 잡히는 걸까요?
C와 C++의 차이점
질문이 두 곳에 있어서 여기도 답변 달아봅니다.
확장자가 *.c 이냐 *.cpp(*.cc) 이냐에 따라 다른 결과가 나옵니다.
유사한 질문을 올린 사람도 있고 어셈블리 레벨에서 답변해 주신분도 있네요. 아래 링크 참조하시면 도움이 될 것 같습니다.
http://www.daniweb.com/software-development/cpp/threads/53814
컴파일러 최적화에 비밀이 있었군요
C에서는 실제로 메모리의 값을 읽어와서 데이터 레지스터의 값을 출력하는데
mov edx, DWORD PTR _a$[ebp]
push edx
C++에서는 그냥 상수 10을 출력해버리네요
push 10 ; 0000000aH
재미있네요 ㅎㅎ
만약 저변수가 함수포인터 였다면 어떻게 될지 생각해보는 것도 재미있겠네요
댓글 달기