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의 값을 바꿔서 다른 곳을 가리키게 하는 것이 불가능합니다.
두가지 기술은 다른 동작을 하기 때문에 무엇을 선호한다 라는 것은 의미가 없을 듯 합니다. 용도에 맞게 선택할 필요가 있습니다.
하지만 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가 되겠습니다만 일단 어디까지나 예입니다. )
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[] 를 사용하는 것입니다.
char *a = "abc"; char b[] =
둘의 차이점은 배열은 수정이 가능하다는건데
예시로처럼 그걸 막아놨으면. . . 차이가 없는것 같습니다.
(근데 지금 b[0] = 'f'; 로 하고 실행해보니 경고만 발생하고 원하는 결과는 출력하네요;
ㅎㄷㄷ 여태까지는 아예 컴파일이 안되는줄 알았는데....이번기회에 좋은것 알았네요~~ : )
흘러가고있는 지금 이 시간에 충실하자.
일단 function안에 이런
일단 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
답변
답변 감사합니다.
실제 코드는 다음과 거의 같습니다.
답변 주신 내용중에 다음 내용이 제가 궁금해하는 핵심인듯싶습니다.
위 경우에는 다음과 같이 두개의 "abc"가 존재하는 것이 맞는지요?
* const 영역에 존재하는 "abc"
* 해당 함수가 실행될 때, stack 영역에 생성되는 "abc"
답변 감사드립니다.
예. 그렇게 보통
예. 그렇게 보통 그렇게 두개가 존재하게 됩니다.
하지만 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
배열의 경우 보통 "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
전웅님 답변
전웅님 답변 감사합니다.
번역시라는 것은 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
댓글 달기