C와 C++에서의 상수 정의에 대한 질문입니다.

ktd2004의 이미지

상수를 정의할 경우 C에서는 define을 C++에서는 const로 정의를 하라고 알고 있습니다.

다음과 같은 테스트를 해보았습니다.(컴파일러는 gcc-4.0.2 입니다.)

/* a.h */
const int a = 1;
 
/* a.c 혹은 a.cc */
#include "a.h"
int main(void)
{
    print("main : %d\n", a);
    b();
}
 
/* b.c 혹은 b.cc */
#include "a.h"
void b(void)
{
    print("bfunc : %d\n", a);
}

C(gcc)로 컴파일 했을 때는, "multiple definition" 에러가 발생합니다.
C++(g++)로 컴파일 했을 때는 아무 문제없이 컴파일됩니다.

그런데, "const int"가 아닌 "const char *"의 상수를 정의했을 때는
C++(g++)에서도 "multiple definition"에러가 발생합니다.

a.h 파일에서 "const char *"가 아닌 "static const char *"로 정의하게 되면
C++(g++)에서 문제없이 컴파일됩니다.

질문은 다음과 같습니다.
1. 일반상수(문자열을 제외한)의 경우에는 C에서는 define, C++에서는 const를 사용해서 상수를 정의하는 것이 가장 좋은가?
1. 문자열 상수의 경우는 C, C++에서 각각 어떻게 해야하는가?
1. C++에서 문자열 상수의 경우 "static const char*"로 상수를 정의한다면 다른 문제는 없는가?
1. C에서도 상수(문자열 상수를 포함한)를 정의할 경우에 "static const"로 정의하는 것은 에러가 발생하지 않습니다.
이 방법은 옳은 방법인가?

미리,, 답변 감사드립니다...

doldori의 이미지

C와 C++의 미묘한 차이 중 하나입니다.
const 개체의 연결(linkage)은 C에서는 외부 연결이지만 C++에서는 내부 연결입니다.
C의 경우 a.h가 #include되면 두 개의 번역단위에서 중복하여 정의한 꼴이 되기 때문에
에러가 나는 것은 알고 계실 것입니다. 그런데 C++의 경우 내부 연결을 가지므로
a.h에서 static const int a; 라고 선언한 것과 같은 효과를 갖습니다. 따라서

Quote:

C(gcc)로 컴파일 했을 때는, "multiple definition" 에러가 발생합니다.
C++(g++)로 컴파일 했을 때는 아무 문제없이 컴파일됩니다.

이런 결과를 보입니다. 그런데
Quote:

그런데, "const int"가 아닌 "const char *"의 상수를 정의했을 때는
C++(g++)에서도 "multiple definition"에러가 발생합니다.

이 경우 const인 것은 a가 가리키는 대상이지 a 자체가 아닙니다.
따라서 이때는 C++에서도 a가 외부 연결을 갖게 되어 중복 정의가 되는 것입니다.
Quote:

a.h 파일에서 "const char *"가 아닌 "static const char *"로 정의하게 되면
C++(g++)에서 문제없이 컴파일됩니다.

이 경우는 static으로 인해 a가 내부 연결을 갖게 되어 중복 정의가 아닌 것이지요.

Quote:

1. 일반상수(문자열을 제외한)의 경우에는 C에서는 define, C++에서는 const를 사용해서 상수를 정의하는 것이 가장 좋은가?

C에서도 #define보다는 const를 사용하는 것이 좋습니다. 문자열을 가리키는 포인터도 포함해서요.

Quote:

1. 문자열 상수의 경우는 C, C++에서 각각 어떻게 해야하는가?

#define을 대체하면서 a가 가리키는 문자열의 변경도 막고 a 자체도 다른 문자열을 가리킬 수 없게 하고 싶다면
// C header
static const char* const a = "some string";
 
// C++ header
const char* const a = "some string";

C++에서도 C처럼 static을 쓸 수 있지만 아래의 이유로 인해 피하는 것이 좋습니다.
Quote:

1. C++에서 문자열 상수의 경우 "static const char*"로 상수를 정의한다면 다른 문제는 없는가?

현재 시점에서는 별 문제 없습니다만, 권하고 싶지 않은 방법입니다.
외부 변수가 내부 연결을 갖게 하는 static은 C++ 표준에서 deprecated feature입니다.
deprecated는 차기 표준에서는 제외될 수도 있으니(물론 계속 남아있을 수도 있습니다만)
사용을 피하라는 의도를 나타내는 것입니다. C++에서는 static을 쓰지 않아도 원하는 효과를
얻을 수 있지요.
Quote:

1. C에서도 상수(문자열 상수를 포함한)를 정의할 경우에 "static const"로 정의하는 것은 에러가 발생하지 않습니다.
이 방법은 옳은 방법인가?

네, #define을 대체하기 위한 것이라면 옳은 방법입니다.
SoftOn의 이미지

1. 일반상수(문자열을 제외한)의 경우에는 C에서는 define, C++에서는 const를 사용해서 상수를 정의하는 것이 가장 좋은가?

저 같은 경우 debug의 용이성을 위해서 const를 사용합니다. 디버깅 중간에서도 해당값을 바로 알 수 있으니 좋죠;;

#ifdef _DEBUG
  const int KKK = 1;
#else
  #define KKK 1
#endif /* _DEBUG */

그리고 저 같으면 예제를 다음과 같이 만들어서 사용합니다

/* a.h */
#ifndef __A_H__
#define __A_H__
#include "stdio.h"
extern const int a;
#endif /* __A_H__ */
 
/* a.c 혹은 a.cc */
const int a = 1;
 
/* main.c 혹은 main.cc */
#include "a.h"
int main(void)
{
    printf("main : %d\n", a);
    b();
}
 
/* b.c 혹은 b.cc */
#include "a.h"
void b(void)
{
    printf("bfunc : %d\n", a);
}

댓글 달기

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