"const char *"와 "const char []"의 차이점이 있나요?

ktd2004의 이미지

const char *a="abc";
const char b[] = "abc";

* 위 두개가 어떤 차이가 있나요?
* 프로그래밍하실때 어느것을 선호하시나요?

kgcrom의 이미지

char *a = "abc";
char b[] = "abc";

둘의 차이점은 배열은 수정이 가능하다는건데

예시로처럼 그걸 막아놨으면. . . 차이가 없는것 같습니다.

(근데 지금 b[0] = 'f'; 로 하고 실행해보니 경고만 발생하고 원하는 결과는 출력하네요;
ㅎㄷㄷ 여태까지는 아예 컴파일이 안되는줄 알았는데....이번기회에 좋은것 알았네요~~ : )

흘러가고있는 지금 이 시간에 충실하자.

ohhara의 이미지

일단 function안에 이런 기술이 있다고 가정하고 설명하겠습니다.

const char *a="abc";
"abc"가 const영역에 잡힙니다. a는 "abc"의 위치를 가리키는 pointer를 가지게 됩니다. "abc"는 함수에서 return해도 사라지지 않습니다. 즉 return a를 해도 함수 밖에서도 "abc"를 참조할 수 있습니다.
a[0]와 같이 접근하려고 하면 memory read가 두번 발생합니다. ( a가 가지고 있는 pointer를 한번 읽고 pointer가 가리키고 있는 data를 한번 읽고 )
a는 pointer이므로 값을 바꿔서 다른 곳을 가리키게 하는 것이 가능합니다.

const char b[] = "abc";
4byte의 stack에 할당해서 할당한 stack의 address를 b가 가집니다. "abc"는 const영역에 잡힙니다. stack에 있는 b에 const에 있는 "abc"를 copy해 넣습니다. b가 가지고 있는 "abc"는 결국 stack안에 들어있기 때문에 함수에서 return하면 사라집니다. 즉 return b를 하고 "abc"를 참조하려고 하면 올바르지 않은 값을 참조할 수 있습니다.
b[0]와 같이 접근하려고 하면 memory read가 한번 발생합니다. ( b는 stack의 address이므로 stack pointer부터 offset으로 구할 수 있고 이것이 가리키고 있는 곳의 data를 한번 읽음 )
b는 array이므로 b의 값을 바꿔서 다른 곳을 가리키게 하는 것이 불가능합니다.

두가지 기술은 다른 동작을 하기 때문에 무엇을 선호한다 라는 것은 의미가 없을 듯 합니다. 용도에 맞게 선택할 필요가 있습니다.

Taeho Oh ( ohhara@postech.edu , ohhara@plus.or.kr ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Digital Media Professionals Inc. http://www.dmprof.com

Taeho Oh ( ohhara@postech.edu ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Alticast Corp. http://www.alticast.com

ktd2004의 이미지

답변 감사합니다.

실제 코드는 다음과 거의 같습니다.

/* 정의 1 */
const char *case_a = "case_a";
const char *case_b = "case_b";
 
/* 정의 2 */
const char case_a[] = "case_a";
const char case_b[] = "case_b";
 
/* 사용 */
const char *case = NULL;
if( case_a) {
    case = case_a;
} else {
    case = case_b;
}
 
printf("case : %s\n", case);

답변 주신 내용중에 다음 내용이 제가 궁금해하는 핵심인듯싶습니다.

const char b[] = "abc";
"abc"는 const영역에 잡힙니다. stack에 있는 b에 const에 있는 "abc"를 copy해 넣습니다.

위 경우에는 다음과 같이 두개의 "abc"가 존재하는 것이 맞는지요?
* const 영역에 존재하는 "abc"
* 해당 함수가 실행될 때, stack 영역에 생성되는 "abc"

답변 감사드립니다.

ohhara의 이미지

예. 그렇게 보통 그렇게 두개가 존재하게 됩니다.

하지만 programmer입장에서는 b를 stack에 잡고 b에 "abc"를 넣는 동작만 이루어 지면 되기 때문에 const에 있는 "abc"의 존재는 programmer입장에서는 의식하고 있지 않게 됩니다. 즉, compiler입장에서는 이 부분에 대해 optimize의 여지가 있으며 optimize를 열심히 해서 "abc"를 const에 놓지 않고 처리할 수 있습니다. 예를 들어 'a'를 일단 b[0]에 넣은 다음에 b[1] = b[0] + 1; b[2] = b[1] + 1; 하는 code를 생성할 수도 있습니다. ( 이 경우에는 이렇게 하지 않는 경우가 더 optimize가 되겠습니다만 일단 어디까지나 예입니다. )

Taeho Oh ( ohhara@postech.edu , ohhara@plus.or.kr ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Digital Media Professionals Inc. http://www.dmprof.com

Taeho Oh ( ohhara@postech.edu ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Alticast Corp. http://www.alticast.com

전웅의 이미지

const char *a="abc";
const char b[] = "abc";
 
if (strncmp(in, a, strlen(a)) == 0)
    ...
 
if (strncmp(in, a, sizeof(b)-1) == 0)
    ...

배열의 경우 보통 "abc" 를 두 벌 가지고 있는 것이 맞습니다만, 컴파일러
구현하기 나름입니다. 예를 들어, 지금 제가 작업 중인 컴파일러에서는
심볼 테이블 구조체에 필드 하나, if 검사문 하나 추가하면 보여주신 코드에서
*a 와 b[] 에 대해 동일한 코드가 생성되도록 할 수도 있습니다 - 별로 소득
없는 최적화인데 이를 위해 tree 순회를 해야 하는 비용이 아깝다는 것이
문제입니다.

제 기준은 기본적으로 *a 를 선호하되 길이 계산이 필요한 경우 번역시에
할 수 있도록 b[] 를 사용하는 것입니다.

--
Jun, Woong (woong.jun at gmail.com)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

ktd2004의 이미지

전웅님 답변 감사합니다.

번역시에 사용(?)할 수 있도록 b[] 를 사용하는 것입니다.

번역시라는 것은 gettext를 말씀하시는 건지요?

gettext 사용시에 "const char*"와 "const char[]"의 차이가 있는지요?
(제가 gettext를 이름만 들어보고, 직접 사용해 본 적은 없어서요. :))

전웅의 이미지

아... 제가 습관이 들어서 "번역시"라고 말씀드려서 오해가 생겼네요.
죄송합니다.

포인터로 할 경우 (그 내용이 고정됨에도 불구하고) 문자열 길이를 굳이
실행 시에 조사해야 하는 반면, 배열로 할 경우 길이를 컴파일 시에 확정할
수 있다는 뜻입니다 - "컴파일(compiling)"이 프로그램 "번역(translation)"
의 일종입니다.

그래서 저 같은 경우 보여주신 배열/포인터를 가르는 기준 중 하나가
길이를 취할 필요성 유무라는 말씀을 드린 것입니다. ^^

--
Jun, Woong (woong.jun at gmail.com)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

댓글 달기

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