C 언어와 C++ 언어에서 const 처리.

cinsk의 이미지

C 언어와 C++ 언어에서 'const' 처리는 조금 다릅니다. :shocked:?

일단 C 언어의 경우, 32, 012, 0x3 등은 정수 상수입니다 (integer constant). 또는 정수 상수식 (integer constant expression)이라고도 합니다. 가변 배열을 제외하고, 배열 크기를 써 준다거나, struct bit-field로 지정할 수 있는 수치는 모두 정수 상수식이어야 합니다.

const int ci = 3

에서, 변수 ci의 타입은 const int입니다. 보통 이런 식으로 'const'가 붙은 타입을 const-qualified type이라고 합니다. 그리고 const-qualified type의 오브젝트는 정수 상수가 아닙니다. 따라서 (가변 배열을 제외하고) 배열의 크기를 지정할 때 ci를 쓴다거나, case 레이블로 쓸 수 없습니다.

C++ 언어 경우, 정수 상수, 정수 상수식 등은 C 언어와 같습니다. 단. const-qualified type의 오브젝트는 정수 상수가 됩니다. 따라서 const int 등으로 선언한 것도 정수 상수 취급을 받아서 배열의 크기를 지정한다거나 case 레이블로 쓸 수 있습니다.

const가 붙은 오브젝트... 말이 좀 이상하죠? 아무리 생각해 봐도 좀 더 나은 표현은 "처음 값을 지정할 때를 제외하고 값을 변경할 수 없는 오브젝트"가 더 나은 표현일 것 같긴 한데.. 그렇다고 상수라고 표현하기 곤란한 게, 이것과 정수 상수와는 전혀 다른 뜻이기 때문에... :sad:

또, C/C++ 모두, const-qualified type으로 선언한 변수는 직/간접적으로 그 값을 변경하면 안됩니다. 이는 undefined behavior에 속합니다. 다음과 같은 코드를 보면 무슨 말인지 쉽게 알 수 있을 것입니다:

const int i = 3;
int *p = (int *)&i;
*p = 4;            /* wrong: undefined behavior */

여담으로 C++에서 위와 같이 C 스타일 타입 변환보다, const_cast를 쓰는 것이 더 바람직합니다.

포인터 선언할 때, const의 위치에 따라서 다양한 종류가 나올 수 있습니다.

1. const int *cip (또는 int const *ip)
2. int * const icp
3. const int * const cicp (또는 int const * const ip)

첫번째는 const int를 가리키는 포인터 ip입니다. 즉 const qualified int (값을 바꿀 수 없는 정수 타입)을 가리키는 포인터입니다. 이 포인터는 얼마든지 다른 const int를 가리키도록 바꿀 수 있지만, 가리키고 있는 대상의 값을 바꿀 수는 없습니다.

const int ci1 = 4, ci2 = 8;
const int *cip = &ci1;
cip = &ci2;      /* ok */
*cip = 0;         /* wrong */

두번째는 일반 정수 타입 int를 가리키는 const 포인터입니다. 즉, 가리키는 대상이 int이기 때문에, 얼마든지 값을 변경할 수 있지만, 포인터 자체가 const이기 때문에 다른 int를 가리키도록 바꿀 수 없습니다.

int i1 = 4, i2 = 8;
int * const icp = &i1;
icp = &i2;      /* wrong */
*icp = 0;         /* ok */

세번째는 const int를 가리키는 const 포인터입니다. 따라서 다른 대상을 가리키도록 포인터를 바꿀 수도 없고, 대상이 가지고 있는 값을 바꿀 수도 없습니다.

const int ci1 = 3, ci2 = 4;
const int * const cicp = &ci1;
cicp = &ci2;      /* wrong */
*cicp = 0;       /* wrong */

참고: ISO C 표준 Sec. 6.7.3.5

참고: ISO C++ 표준 Sec. 5.2.11.7, Sec. 7.1.5.1

Forums: 
hey의 이미지

고맙습니다. 도움이 많이 되었습니다. :)


----------------------------
May the F/OSS be with you..


doldori예요의 이미지

C와 C++에서 const의 또다른 차이점은 연결(linkage)이죠.

C에서는 블럭 외부에 선언된 const 개체는 static을 붙이지 않으면 외부 연결을 갖습니다. 그런데 C++에서는 extern을 붙이지 않은 const 개체는 내부 연결을 갖지요. 따라서 C++에서는 const 개체의 정의를 헤더에 넣어도 one-definition rule을 위배하지 않습니다.

예를 들어 C의 경우 배열 크기를 헤더에서 #define으로 쓸 때가 많은데, C++에서는 이러한 매크로를 const 정수형으로 완벽하게 대체할 수 있다는 뜻이죠.

결론적으로 말하자면 C는 일관성을 추구하고 있고, C++은 일관성을 희생하면서 사용의 편의성을 높였다고 할 수 있겠습니다.

HDNua의 이미지

이런 사실이 또 있는지 몰랐네요.
좋은 정보 더 알아갑니다 ㅎㅎ

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

xster의 이미지

C, C++의 linkage 차이를 말씀하셨는데 차라리 const int 를 상수 정수와 같은 개념으로 쓴다고 정의된 것에 의한 것이 더 맞지 않을까 생각됩니다.
간단히 그냥 #define 의 전처리와 같지만 컴파일러 수준에서 관리해준다고 생각할 수도 있을 것 같네요.

Hyun의 이미지

C++ 학교에서만 잠깐 접했었는데... 미묘하군요..

HDNua의 이미지

2006년에 쓰신 글이 6년이나 지난 지금에도 제게 도움을 주고 있습니다.
감사드립니다 ㅎㅎ

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

RiamG의 이미지

공들인 소중한 정보 잘 보겠습니다^^

고요한밤 거룩한밤 어둠에 묻힌밤

댓글 달기

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