const 변수값 변경 관련해서 질문드립니다

Pike의 이미지

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이 출력됩니다.
혹시나 싶어서 포인터의 값과 정수변수의 주소값을 확인해보니 일치하였습니다.
어떻게 이런게 가능한 것인가요?

ifree의 이미지

C 인지, CPP 인지?

Pike의 이미지

CPP입니다.

ifree의 이미지

CPP 에서는 C 와 달리 test 값의 storage 가 생성되지 않을 수도 있습니다.

즉, 출력된 0는 storage 에 담긴 값이 아니고, 컴파일러의 constant table 에서 나온 값이 아닐까 생각되는데 저 경우가 다른 컴파일러에서도 나올지는 모르겠네요.

Pike의 이미지

CPP에서는 CONST값은 실제 메모리공간에 할당되지 않는다는 말씀인가요?

ifree의 이미지

위 경우와 같이 주소를 참조한다던가, 다른 파일에서 extern 으로 선언되어 있는 경우 등을 제외하고는 메모리 영역이 할당되지 않습니다.
그런데 저 경우는 storage 가 잡혀 있으니 에러가 나올 것 같은데 이상하네요.

klyx의 이미지

포인터 형변환 시키면 뭐든지 다 되지 않나요?
데이터영역에 들어가는 건0이지 test가 아니니까 일단 컴파일은 문제가 없을테구요.
다만 test가 0으로 나온건 컴파일러 최적화가 아닐까 합니다.

DarkSide의 이미지

씨ㅍㅍ에서는 포인터 형변환도 제약이 많습니다.
포인터를 보이드형으로 바꾸었다가 다른 걸로 바꾸는 것도 잘 안됩니다.

Pike의 이미지

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의 값을 바꾼다는게 별로 이상한거 같지 않습니다.

bushi의 이미지

왜 C++ 에선

...
  printf("%d\n", test);
...


...
  printf("%d\n", 0);
...

처럼 컴파일러가 해석하는 지 궁금해하는 것 같습니다.
최적화오류가 아니냐고 의심하는 분도 이걸 말씀하시는거고요.
volatile 키워드면 증명이 되겠죠.
Pike의 이미지

위의 코드에서 int의 선언에 static으로 선언하니 메모리 침입 오류가 뜹니다.
뒤적거려보니 static const로 선언하면 메모리 DATA영역에 잡히는 것이 아닌 상수영역에 잡혀서 그렇다고 하는데
Const 지역변수의 경우에는 stack영역이 아닌 다른부분에 메모리가 잡히는 걸까요?

익명 사용자의 이미지

질문이 두 곳에 있어서 여기도 답변 달아봅니다.

확장자가 *.c 이냐 *.cpp(*.cc) 이냐에 따라 다른 결과가 나옵니다.

유사한 질문을 올린 사람도 있고 어셈블리 레벨에서 답변해 주신분도 있네요. 아래 링크 참조하시면 도움이 될 것 같습니다.

http://www.daniweb.com/software-development/cpp/threads/53814

Pike의 이미지

C에서는 실제로 메모리의 값을 읽어와서 데이터 레지스터의 값을 출력하는데
mov edx, DWORD PTR _a$[ebp]
push edx
C++에서는 그냥 상수 10을 출력해버리네요
push 10 ; 0000000aH

재미있네요 ㅎㅎ
만약 저변수가 함수포인터 였다면 어떻게 될지 생각해보는 것도 재미있겠네요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.