C언어에서 const 사용 관련 질문입니다.

HDNua의 이미지

코드
-----
#include

int isChanged(const int *target, const int origin);

int main(int argc, const char * argv[])
{
int num1 = 10;
printf("isChanged? %d\n", isChanged(&num1, num1));
printf("num1: %d\n", num1); // 20 출력: 값이 변함

const int num2 = 10;
printf("isChanged? %d\n", isChanged(&num2, num2));
printf("num2: %d\n", num2); // 10 출력: 값이 변하지 않았음

const int num3 = num1 + num2;
printf("num3: %d\n", num3);

return 0;
}

int isChanged(const int *target, const int origin)
{
int *temp = (int *)target;
*temp = 20;

printf("*target: %d\n", *target);
printf("*temp : %d\n", *temp);

return (*target!=origin);
}
-----

결과:
-----
*target: 20
*temp : 20
isChanged? 1
num1: 20
*target: 20
*temp : 20
isChanged? 1
num2: 10
num3: 30
-----

iMac에서 Xcode로 코딩하고 있습니다. 결과가 이렇게 나오는데 질문이 있습니다.
보시는 것처럼 isChanged 함수에서 target과 temp를 출력하고 있습니다. 첫 번째에서는 const int* 타입으로 인자를 받았지만
temp 포인터에 형 변환을 해서 집어넣어줬기 때문에 이를 이용해 main 함수의 num1 값을 바꿀 수 있었다고 생각했고 실제로 그랬는데,
const int로 선언해준 num2에 대해서는 값이 그대로네요.
이상한 건 isChanged 함수에서 값이 바뀌었는지 출력을 통해 보려고 했는데, *target의 값이 20으로 변해있었다는 겁니다.
왜 이런지 설명해주실 수 있으신가요?

klyx의 이미지

컴파일러 최적화가 일어난 듯합니다.
const로 선언되었고, 함수 인자로 넘길 때에도 const로 넘기고 있으므로 컴파일러는 이 값이 바뀌지 않을 거라고 예상하고 상수로 10을 밖아버린 듯하네요.

HDNua의 이미지

질문 올릴 때마다 매번 소중한 답변 정말 감사드려요.
한 가지 더 궁금한 점이 생겼는데, 컴파일러의 '최적화'는 무엇인가요?
최적화라고 하면 전 그냥 필요없는 것들을 삭제해 프로그램을 보다 빠르게 돌릴 수 있게 하는 일 정도로만 알고 있었는데요. (아직 지식이 짧습니다ㅠ)
그리고 컴파일러의 최적화도 대학교에서 자주 가르치는 과정인가요? 아니면 어떤 경로로 이에 대해 공부할 수 있을까요?

다시 한 번 감사드립니다. ㅎㅎ

저는 이렇게 생각했습니다.

klyx의 이미지

프로그램 수행에 도움되게 개선하는 여러가지 행위들을 다 최적화라고 할 수 있습니다.
그리고 말씀하신 것처럼 불필요한 것들을 삭제하는 최적화가 대부분입니다.
질문 내용에서 const int로 정의된 상수를 리터럴로 치환하는 것은 C++의 표준에서 보장되는 내용이지만, 그렇지 않다고 하더라도 이러한 행위는 불필요한 변수 할당이나 대입을 피하기위한 최적화라고 볼 수 있겠지요.
동일한 변수에 대한 연속적인 값의 대입이 있다면 마지막 대입만 남긴다던가, 함수의 마지막에 반환되는 객체에 대해서는 복사를 생략한다던가, 반복되는 함수 호출을 생략하고 인라이닝한다던가, 루프를 없애는 루프 언롤링 등등 다양합니다.
제가 컴파일러를 제대로 공부해본 적은 없어서 하나하나 열거하지는 못하겠네요.

HDNua의 이미지

그렇군요. 답변 감사합니다.

저는 이렇게 생각했습니다.

bluekyu의 이미지

저의 경우
num2: 20
num3: 30
이 나오고, 최적화 없이 하면
num2: 20
num3: 40
이 나옵니다.

그리고 이게 이상해서 저도 찾아 봤는데, Undefined Behavior로 정의가 되어있네요.
http://kldp.org/node/68231
http://stackoverflow.com/questions/11641613/change-const-int-via-an-int-pointer-surprising-and-interesting
http://stackoverflow.com/questions/2508605/modifying-a-const-through-a-non-const-pointer

/*** Signature ******************
* blog: http://blog.bluekyu.me/ *
********************************/

HDNua의 이미지

첫 번째 링크도 모르던 정보를 알 수 있어서 너무 좋았습니다.
저는 특히 두 번째 링크의 설명이 참 마음에 드네요.
C++ const 타입으로 선언한 변수는 정수 상수로 취급하여
컴파일러가 이 변수를 만나면 그냥 정의된 값으로 바로 치환해버린다라.. 와ㅎㅎ

아, 그런데 개발 툴에 최적화 옵션을 설정해줄 수 있나요?

저는 이렇게 생각했습니다.

klyx의 이미지

대부분의 개발 툴은 컴파일 옵션을 따로 줄 수 있게 되어있습니다.
그조차 안된다면, 그냥 컴파일러 자체를 옵션 들어간 걸로 지정해버리는 방법도 있습니다.

HDNua의 이미지

또다시 감사합니다ㅎㅎ

저는 이렇게 생각했습니다.

HDNua의 이미지

결론은 정의되지 않은 행동이니 사용하지 않는 게 좋다는 것이군요.. ㅎㅎ

저는 이렇게 생각했습니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.