C언어 - 로컬 변수 선언의 차이점[완료]

rev7707의 이미지

아래 함수중 f1()는 정상적인 결과를 내고 f2()는 쓰레기 값이 나옵니다.
왜그럴까요?
둘다 쓰레기 값이 나와야 하지 않나요?
두 변수의 저장공간이 서로 다를까요?

1 #include
2
3
4 char *f1()
5 {
6 char *str = "CryptoTelecom";
7
8 return str;
9 }
10
11
12 char *f2()
13 {
14 char str[] = "CryptoTelecom";
15
16 return str;
17 }
18
19 int main(void)
20 {
21 printf("1:%s\n",f1());
22 printf("2:%s\n",f2());
23
24 return 0;
25 }

brucewang의 이미지

우선, 컴파일러는 두 동일 스트링 "CryptoTelecom" 을 동일한 데이터영역에 저장합니다.

이것을 char* 로 그 시작 메모리 주소를 저장한 것이냐, 아니면 char[] 로컬 배열에 문자열을 복사한 것이냐의 차이 입니다.

f1은 데이터 영역 주소 자체를 반환하니까 문제가 없고, f2는 로컬변수 자체의 주소를 반환하니까 함수영역을 벗어나면서 로컬변수는 사라졌으므로 쓰레기 값이 출력되는 것입니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

cppig1995의 이미지

C 컴파일러는 brucewang 님의 말씀처럼 최적화할 수 없습니다. "..."는 상수이고, []="..."는 변수입니다.
상수는 상수 영역에 들어가고 변수는 변수 영역에 들어가겠죠?
[]=..."는 복사가 아닙니다. 이건 초기값(initializer)으로써 작용합니다.
brucewang님의 말씀대로라면 int a[3] = {0, 1, 2};도 복사입니다.

어쨌든, 상수 영역은 스택 상에 있지 않기 때문에 함수의 return과 관련이 없습니다.
지역 변수는 스택 상에 있으므로 함수의 return에 따라 덮어써질 수 있습니다.
--
임수서룬뫼 윤희수 {cppig1995/돼지군}

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

brucewang의 이미지

제 글을 상당히 잘못 이해한것 같습니다.

동일한 "..." 문자열이 있을경우 그 문자열 자체의 공간을 말하는 것입니다. 님이 상수영역이라고 말한 공간에 말이죠. 정말 같은 문자열이 별도의 공간을 차지할 것이라고 생각한다면 한번 다시 확인 해보길 바랍니다.

char*, char[] 등의 로컬 변수가, 하나는 상수영역의 주소만을 저장하고 그 값이 return 되는 것이고, 하나는 님이 얘기한 '상수영역' 의 데이터가 로컬 배열 변수에 복사 된 뒤 다시 그 배열변수의 주소가 return 된 것입니다.

이미 상수 영역에 정의된 문자열 내용을 배열 변수에 데이터를 초기화(Initializa'tion') 하는 것은 결국 데이터 내용의 복사 입니다.

뭐 이거야 기초적인 이야기고, 아마도 다른 사람의 글 내용이나 수준을 미리 짐작해 버리고 오해해 버린건 아닐까 싶군요. 다시 제 글 내용을 확인해 보길 바랍니다. 저는 ".." 문자열 자체와 로컬변수 char[]의 내용이 동일 주소라고 말하는 것이 아닙니다. 님의 상상속의 인물을 저에게 대입하신건 아닌가요?

PS> 스택영역의 값들이 리턴될때 그것이 덮어써질 수 있다는 것은 어떤 의미인지 잘 이해를 못하겠군요. 좀 더 자세히 설명해 주면 좋을것 같습니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

gardner의 이미지

아가야, brucewang 님 설명이 딱히 틀린건 아니란다.
좀 더 엄밀히 말하자면, 스택이니 상수 영역이니 하는 특정 구현 쪽에 치중한 니 설명보다는
오히려 brucewang님 설명이 더 일반적이고도 C의 기본에 충실한 설명이란다.

물론 너는 그걸 제대로 다 읽어보진 않고 니 꼴릴 때마다 꺼내서 누구 까는 데에만 쓰겠지만
C 표준 문서 정도는 가지고 있지?
가서 찬찬히 전체적으로 읽어보려므나.
상수영역이니 변수영역이니 같은 얘기는 한줄도 안써있단다.
표준문서에서는 그걸 상수영역이라고 안하고 static duration을 갖는 배열이라고 한단다.

게다가 "..."는 상수가 아니고 문자열 상수란다.
한국어로는 둘다 상수라고 쓰니까 같은 종류인줄 아는가 본데
너도 영어 쫌 읽지? 가서 원문 확인해보렴
constant랑 string literal이란다.
이건 아주, 대단히 큰, 맞아 죽을 정도의 실수를 한 거란다.
사소한걸로 큰 형아들 걸고 넘어져 까는걸 좋아하는 니 평소 태도대로라면 말이다.

그리고 그걸 복사라고 해도 딱히 틀린 설명은 아니란다.
아 물론 큰 형아들 실수라면 사소한 것도 놓치지 않는 매의 눈을 한 너에게는
아주 크게 다르고 잘못된 일로 보이겠지.
하지만 개념을 곧이 곧대로 설명하는게 아니라 일반적인 용어로 풀어 설명 한다고 하면
'초기화시킨다'나 '복사한다'나 크게 차이가 있는건 아니란다.

큰 형아들이 노는 물에 끼어서
형들보고 틀렸다고 지적하면서 놀면
자신이 같은나이의 저 코찔찔이 중딩들하고는 차원이 다른
뭔가 대단한 존재가 된 것처럼 우월감이 느껴지는건 잘 알겠는데,
적어도 틀리지 않은걸 틀렸다고 우기면서 끼어드는건 좀 자제해야 하지 않겠니?

KLDP는 니 중2병을 만족시켜주기 위한 공간이 아니란다.

세이군의 이미지

말조심 하십시요.
아무리 상대가 어린 사람이 확실하다고 하더라도 온라인 상에서 이렇게 이야기하는 것은 올바른 예절이 아닙니다.

bootmeta의 이미지

토의 내용의 옮고 그름과 상관없이 꽤 눈에 거슬리는 군요.
적절한 충고는 수용가능하나, 그 범위를 넘어가면 단순히 모욕을 주는 행위입니다.

여러 글타래에 꽤 거슬리는 댓글들을 올리는 님을 보고 있자니 초등학교 방학이 얼른 끝났으면 좋겠다는 생각이 드는군요.

gardner의 이미지

풉 너나 나나.
중딩아 라고 쓰면 '단순히 모욕을 주는 행위'이고 '초등학교 방학이 얼른 끝났으면 좋겠다'라고 쓰면 '적절한 충고'냐?
네 혓바닥에 면도칼 빼물은거 다보여.

bootmeta의 이미지

전 gardner님에게 충고할 생각없습니다.
스스로 얼마나 쪽팔린지 알라고 한마디 던졌을 뿐입니다.

jick의 이미지

가입한지 24시간도 안되어 상당한 글을 써댔는데 거의 대부분이 남을 비방하고 시비거는 글이군요. 게다가 특정사용자(임수서룬뫼 님)를 상대로 인신공격을 집중하고 있습니다.

이정도면 인신공격용 멀티 계정으로 판단해도 될 듯합니다. 권순선 님 보시면 좀 조치해 주시길 부탁드립니다.

* 다른 모 글타래를 보면 마치 제가 욕먹어서 분해서 그런 것처럼 보일 수도 있겠습니다만...... 그런 의도는 없음을 말씀드립니다. 전 대인배라서 욕설용 멀티계정 따위는 신경쓰지 않습니다. -_-;;;;;;

gardner의 이미지

다른 글타래에서 저한테 욕먹어서 분해서 그런거 딱 맞는데 뭘 아니라고 빼십니까. 제가 링크 적어드릴께염 다들 가서 직접 보시고 판단하세요.

http://kldp.org/node/96787

으이구... jick님 몇살이십니까? 몇살인데 중딩 뒤에 숨어서 남이나 까고 그래여?
보는 제가 다 얼굴이 화끈거립니다.

저쪽에선 미친눅대란 분한테 옛날에 당한게 두고두고 분해서 시비를 거시더니만
여기선 또 저한테 앙심품고 트롤이니 뭐니 그러시네요.
옛날에 당한 사람마다 모두 이름 적어놓고 두고두고 보복할려면 참 바쁘실 것 같습니다.

미친눅대의 이미지

무슨 근거로 멀티 계정이라고 생각하는지 모르겠지만 누구 주장처럼 멀티 계정이 맞다면 과연 누구 멀티 계정인지 저도 궁금하군요.

운영자님께서는 서버 로그를 볼 수 있을테니 트롤 신고 처리 시 가능하다면 누구 멀티 계정인지 꼭 함께 밝혀주시기 바랍니다.

pizza1977의 이미지

생로병사에 대해 다시 한번 확인해 보세요.

포탈이는 불사신

-------------
포탈이는 불사신

magingax의 이미지

두경우다 로컬 스택에 스트링을 넣었다..리턴하는데.
이러시면 안됩니다. 로컬스택은 어찌 될지 모르니..

LISP 사용자모임
http://cafe.naver.com/lisper
방송기술 개발업체
http://playhouseinc.co.kr

prio의 이미지

포인터와 배열의 차이에서 오는 결과입니다.

4 char *f1()
5 {
6 char *str = "CryptoTelecom";
7
8 return str;
9 }

이 때는 str을 위해서 스택에는 4byte가 할당됩니다. (32-bit pointer로 가정)
"CryptoTelecom"은 리터럴로 해석되어 data section에 배치되고,
str은 data section 중에 특정 위치의 주소를 값으로 갖게 됩니다.
따라서 함수의 리턴값은 data section의 어떤 주소가 되고,
함수가 리턴되더라도 data section은 변경되지 않기 때문에 제대로(?) 출력이 됩니다.

12 char *f2()
13 {
14 char str[] = "CryptoTelecom";
15
16 return str;
17 }

이 때는 str을 위해서 스택에 14byte (strlen("CryptoTelecom") + 1, align 고려하지 않음;; )
가 할당되고, 함수의 리턴 값은 스택 영역의 어떤 주소가 됩니다.
이때 str 배열의 초기화는 컴파일러에 따라 달라지게 되는데,
gcc의 경우 64byte 이하의 문자열은 "move immediate" instruction을 이용해 처리하므로,
"CryptoTelecom"은 data section에 할당되지 않고 그냥 코드 중에 immediate 값으로 처리됩니다.
(요 문제 때문에 brucewang 님과 임수서룬뫼 님이 모두 맞는 얘기를 하며 다투시는(?) 것 같네요.)
함수의 리턴값은 스택의 어떤 주소가 되고, str 배열 영역은 printf의 콜스택과 겹치기 때문에 값이 깨지게 됩니다. 그래서 제대로(?) 출력이 안되는 거구요.

brucewang의 이미지

감사합니다. prio 님께서 말씀하신 gcc의 얘기는 잘 모르던 내용이었습니다.
저의 단순한 기억만으로 답변을 올린것에 후회를 하고 있습니다.

제가 '임수서룬뫼' 회원에게 답변을 요구하는 댓글을 다시 남긴것은 몇가지 이유가 있습니다.

저의 경우 KLDP는 오랜동안 리눅스 프로그래밍과는 다른 일만 하다가 Linux 프로그래밍을 시작하면서 많은 가르침을 얻기 위해 들어 온 지라 가입 일자가 얼마 안됩니다.

제가 '임수서룬뫼' 회원의 프로필을 보니 중학생이라 되어 있고 몇몇 글타래를 보니 과학영재로 선발되기를 희망하는 청소년인것 같았습니다. 그런데 저 뿐만 아니라 다른 회원들께도 글을 올린 것을 보면 상대방의 의도 파악은 하지 않은 채 자신만 뭔가를 알고 있는 듯한 글을 많이 올리더군요. 훨씬 나이 많은 사람들이 존댓말 써주고 같이 토의하는 것을 자신이 우월하기 때문이라고 착각하는게 아닐까 싶더군요.

저는 나이와 상관없이 재능이 있는 사람들을 존중하고, 우리나라같은 척박한 환경에서 잘 성장하여 우리나라에 큰 일을 하는 사람이 되기를 바랍니다. 물론 중학생인 데다가 공부만 아는 학생들 일부의 경우, 다른 사람과의 커뮤니케이션은 어떻게 해야 할 지 모르는 경우가 많다는 것을 압니다. 어쩌면 그것이 자신을 차별화 시키는 것이라고 생각할지도 모르겠습니다.

하지만, 천재가 아니라 영재로 살아가서 사회에 공헌을 하려면 지식 이외에도 몇가지를 더 수련해야 한다고 봅니다. 영재 뿐만 아니라 천재도 그런 것은 마찬가지 아닐까요? 물론 저를 기초도 모르는 사람처럼 취급한 것 같아 기분이 상하기도 했지만, 누군가라도 이렇게 그 회원이 스스로 뭔가 실수를 했는지 알아보도록 해 주어야 한다고 생각했습니다.

또, 그 외에도 사실 그 회원이 말한

Quote:
["어쨌든, 상수 영역은 스택 상에 있지 않기 때문에 함수의 return과 관련이 없습니다.지역 변수는 스택 상에 있으므로 함수의 return에 따라 덮어써질 수 있습니다." ]

내용이 명확하지 않고, 또 혹시나 제가 정말 모르는 내용에 대한 정보를 주는 것일지도 몰라서 명확한 표현을 요구한 것입니다.

그 회원 스스로 다른사람의 글의 행간이나 의미를 파악하기 보다는 우선 상대방이 정확한 용어 사용과 명확한 표현을 안하면 글 내용을 임의판단하는 것 같아서, 그 회원 스스로도 우선 명확해 지라는 표현입니다.

예를 들어 말입니다. 저의 글 내용은 명확하게 다음과 같다고 치겠습니다.

"어떤 서브루틴이 위에 있는 다른 서브루틴을 호출할 때 caller는 callee에게 전달할 파라미터들, 그리고 그 callee가 return하는 값을 저장할 공간들을 stack에 psuh할겁니다. 이때 callee가 사용하는 local variable을 제대로 보존하기 위해 activation record나, IP, SP 등을 잘 처리할 수도 있겠죠. 그 실제 구현 방법이야 컴파일러에따라 또는 다른 환경에 따라 다를 것이라고 생각하지만, 자세한 것은 저는 잘 모르겠습니다.

어쨌든 대단히 간단하게 축약하자면 서브루틴이 사용한 로컬 변수는 서브루틴이 종료되면 사용할 수 없다고 가정하는것이 편하다고 생각하고 있습니다. 여기 이 글타래에서 중요한것은 return 값인데, char str[] 변수를 return str; 하면 로컬 영역의 배열 공간의 첫 주소가 리턴되는 것입니다. caller의 경우는 char 타입에 대한 포인터 공간만 할당하고 있었을 것이기때문에, 따라서 그 주소는 caller 에게는 무의미한 것이 됩니다.

여기서 가장 중요한 이슈는 스트링 리터럴 자체의 공간과, 그것이 따로 로컬에 복사된 상태인가 아니면 별도의 데이터영역에 저장되어 있는 것인가의 차이라고 생각합니다. char* str;의 경우 return str 하면 데이터 공간의 주소가 반환되는 것이므로 문제가 없는 것이라고 답변을 드렸던 것이죠."

이런식으로, 도대체 어떤 의미로 글을 올렸던 것인지 보다 명확한 설명을 바란다는 것입니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

grassman의 이미지

다만 두 분이 보는 관점이 좀 다른 것 같습니다. brucewang님은 특정 architecture에 의존하지 않고 이론적인 차원에서 내용을 보고 계신 것 같고 임수서룬뫼님은 x86의 특정 컴파일러에 대한 결과로 답변을 하신 것 같습니다.

컴파일러의 세부 특성을 알고 있으면 좋은 일이겠지만 결론적으로 보면 C 언어의 설계에서 의도하지 않은 내용에 관해 얘기를 하고 있는 것이므로 특정 architecture에 대한 예를 든 것에 대해서는 명확한 설명이 있어야 할 듯 싶군요.

저같은 경우 임수서룬뫼님같이 low level에서 현상을 관찰하는 경향이 있어서 brucewang님과 같은 분들의 이해 방법과는 좀 차이가 있습니다. (디버깅을 위해 이론과 실제의 격차를 좁혀야 하는 생존형 이해 방식이라고 보시면 되겠습니다) 같은 내용을 두고 사람들 간에 이해하는 방법도 다양하므로 그 차이를 굳이 좁혀야 할 필요성은 없을 것 같다는 것이 제 개인적인 생각입니다.

jick의 이미지

훨씬 나이 많은 사람들이 존댓말 써주고 같이 토의하는 것은,

그러는 게 당연하기 때문입니다. 적어도 제 경우엔 그렇습니다.

- 나이는 숫자일 뿐.

brucewang의 이미지

참고로 제가 임수서룬뫼 님께 질문한 내용이 piro님의 설명하신 내용을 내포했던 것이라면 지당한 것이군요.....

Quote:
함수의 리턴값은 스택의 어떤 주소가 되고, str 배열 영역은 printf의 콜스택과 겹치기 때문에 값이 깨지게 됩니다. 그래서 제대로(?) 출력이 안되는 거구요.

임수서룬뫼 님의 의미를 잘 못 이해했던 것 같습니다.
piro님 감사합니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

김일영의 이미지

물론 다들 아시겠지만 1번도 좋은 사례는 아니라고 봅니다.

문자열 리터럴은 가급적 함수 내부에서만 쓰고
리턴값으로 넘겨주는건 바람직하지 못하다는 생각입니다.

왜냐면 모든 문자열을 리터럴로 정의해서 쓸 수 있는 경우는 거의 없는데
어떤 함수는 메모리를 할당받아서 문자열을 만들고
어떤 함수는 문자열 리터럴을 리턴하고 그러면
매우 헷갈리더군요.

그런데 X86 특정 컴파일러의 구현 기준으로 풀이하는 것보다는
표준에 근거한 풀이가 당연히 더 타당하고 저 역시 지향하는 바입니다만
초기화는 복사가 아니라는 말은 맞는 것 아닌지요?
초기화를 위해 별도의 데이터 공간이 확보되었다가
변수로 내용이 복사되는 식으로 처리되는 것은 아닙니다.

prio의 이미지

논의가 뭔지 모르게 제가 이해할 수 없는 방향으로 흘러가고 있는데요;;
임수서룬뫼 님의 평판이야 제가 알바 아니고 -_-;
표준 얘기는 왜 나오고, '복사'냐 아니냐가 왜 그렇게 민감한 사항인지 잘 모르겠습니다. 허허.

원질문자께서는 이미 두 경우 모두 문제가 있는 것이라고 인지하신 상태에서 어떤 이유로 하나는 '제대로'된 값을 출력하고 다른 하나는 그렇지 않은지를 질문하셨고, 그것은 제 이해로는 표준의 문제라기 보다는 표준의 구현이 어떤가에 대한 질문이라고 생각됩니다.
꼬투리를 잡고 싶은 것은 아닙니다만, 그런 맥락에서 brucewang 님께서도 처음에 '컴파일러가 어찌어찌한다'라고 설명하신 것 아닐까 합니다. 저로서는 그런 식의 대답이 아주 자연스럽게 느껴지구요.
C라는 게 java 등과 달리 메모리를 직접 가지고 노는 언어다 보니, 뭔가를 설명하려면 컴퓨터 구조와 뗄레야 뗄 수 없는 상황아니겠습니까.
그와 달리 표준은 모든 현상을 설명하기 위한 것이 아니고 '이러이러하게 코드를 작성하면 어떤어떤 행동을 보장해야 한다'라는 정도의 의미를 가지는 일종의 규약이기 때문에 원질문자께서 궁금해하시는 이유를 설명하기는 어렵다고 봅니다.

그리고 '복사'라는 단어를 각각 어떻게 쓰고 계시는 지는 모르겠는데,
배열을 초기화 하려면, 실행시간에 초기값이 하늘에서 뚝 떨어지는 것도 아니고;;
어쨌거나 실행 파일 어딘가에 초기값이 자리를 차지하고 있는 것이구요.

그게 코드 영역에 immediate 값으로 있을 수도 있고, 데이터 영역에 옹기종기 모여 있을 수도 있고
어디에 있던간에 함수 안에서 선언된 배열을 할당한 메모리로 옮겨져야 하는 건데..
그게 move instruction을 이용하면 '복사'가 아니고, memcpy()를 이용하면 '복사'인건가요? ;;;

gardner의 이미지

표준이 만능은 아니지만 적어도 이 문제는 표준의 범위 내에서 설명할 수 있고 해결할 수 있는 문제입니다.

정확히는 대상체의 storage duration과 관련된 문제입니다.

표준이고 나발이고 다 집어치우고 설명하더라도,
왜 문자열 상수는 함수 외부에서 써도 되고 문자열 배열은 쓰면 안되는가
하는 질문에 대답하기 위해서는 이 두가지의 storage duration의 차이에 대해
어떤 방식으로든 짚고 넘어가야 합니다.

그걸 가지고 구현체에 특화된 방향으로 설명하자면
'상수는 상수 영역에 있고 변수는 스택 영역에 있다'
라고 설명할 수도 있겠지만 좀 더 일반적인 개념으로 설명하자면
'문자열 상수는 어느때 생성되어 어느때 소멸되고,
함수 내의 지역 문자열 배열은 어느때 생성되어 어느때 소멸된다'
라고 말하는 것이 정확합니다.

듣는 사람 입장에서도 메모리 구조가 어떻고 스택과 힙이 어쩌고 하면서
컴퓨터 구조에 대한 썰을 길게 풀어놓는 것보다는
C언어적인 개념만으로 끝마치는게 깔끔하고 좋지 않습니까?

prio의 이미지

6 char *str = "CryptoTelecom";

여기에서 스트링 리터럴이 static storage duration을 가진다면 표준으로 설명가능하고,
그렇지 않다면 컴퓨터 구조 및 컴파일러에 대한 썰을 풀어야 하겠지요.

저는 언뜻 automatic일 거라 생각하고 표준 문제가 아니라고 감히 말한건데..
다시 생각해보니 static 일 수도 있겠네요;;;

김일영의 이미지

예를 들면 int a = 1;
이런거 보고 복사라고 생각하지는 않을 겁니다.

아마도
int b;
b =a;
이런 거 정도(?)를 복사라고 하겠지요.

뭐 int a = 1; 에서 1은 그럼 프로그램 어딘가엔 들어있겠지
하늘에서 떨어졌냐고 할 분이 있을지 모르겠으나
그러면 복사 아닌 것이 없겠지요.

여하튼 초기화 시키는 값은 그 변수 이전에 데이터가 저장(?)되는건 아니니
'복사'와는 구별이 되는 것 같습니다.

초기화는 복사가 아니라는 댓글은 분명히 문자열 배열의 초기화도
저것처럼 복사가 아니라는 말씀으로 보입니다.
제가 알기로도 그렇습니다.

구현이 아니라 표준에 근거를 두고 해석을 해야 한다는 것은 제 신조(?)이기도 한데
이 부분은 왜 move 등등이 언급되는지 좀 이해가 안됩니다만 그것은 별개로 보더라도
복사라는 말은 원 소스의 수명을 언급할 수 있을때에나 의미가 있지 않나 싶습니다.

kaeri17의 이미지

C에서 문자열에대해서 초기화와 복사는 사실 잘 구분 되지 않습니다.

char a[]="i am sam";
 
char a[9];
strcpy(a, "i am sam");

이 두개의 경우 사실 별 차이를 내지 않고요, 첫번째 코드를 두번째 코드처럼 컴파일 해 주는 컴파일러도 있습니다.

아까 위에서 언급된 gcc의 경우 좀 다르게 초기화를 시키긴 합니다만(숫자 초기화처럼) 사용자 수준에서 알아채기는 힘들죠.

그리고

char* a="i am sam";

이 코드의 경우 분명히 앞의 것과 차이가 있죠.
brucewang의 이미지

음... 조금 혼동이 되서 질문 드립니다. 제가 잘 모르는 것 같아서요.

piro 님의 설명을 인용하자면,

Quote:

12 char *f2()
13 {
14 char str[] = "CryptoTelecom";
15
16 return str;
17 }

이 때는 str을 위해서 스택에 14byte (strlen("CryptoTelecom") + 1, align 고려하지 않음;; )
가 할당되고, 함수의 리턴 값은 스택 영역의 어떤 주소가 됩니다.
이때 str 배열의 초기화는 컴파일러에 따라 달라지게 되는데,
gcc의 경우 64byte 이하의 문자열은 "move immediate" instruction을 이용해 처리하므로,
"CryptoTelecom"은 data section에 할당되지 않고 그냥 코드 중에 immediate 값으로 처리됩니다.

이런 경우 '김일영' 님의 말씀대로라면 초기화에 해당하는 것인지요, 아니면 복사에 해당하는 것인지요?
반대로, 64byte 이상의 동일 스트링 리터럴이 있을 경우 (데이터섹션에 미리 존재)는 복사인가요, 초기화 인가요?

무식한 질문 죄송합니다...

PS> 좋은 코멘트 감사합니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

kaeri17의 이미지

C언어 명세에 따르면 둘다 초기화입니다.

하지만 C에서 문자열에 대해서 초기화냐 복사냐를 따지는건 별로 그닥 의미가 없다고 생각하시는게 더 맞을 듯 합니다.

초기화도 복사처럼 일어나고 그냥 명세에 의해서만 초기화인 경우가 많거든요.

물론 아까도 말했듯이 char*의 경우에는 분명 초기화와 대입을 구분 할 수 있습니다.

하지만 char배열의 경우 그냥 그게 그겁니다. 복사가 초기화는 아니지만 초기화는 복사와 별다른 차이를 내지 못합니다.

하지만 보기 깔끔한 코드를 원하면 분명 초기화가 나을 듯 합니다.

그리고 로컬 스택의 주소값 반환은 어쨋듯 하면 안되는 거니 별로 그때 뭔일이 일어나는지는 관심 가질 필요가 없다고 생각됩니다.

컴파일러는 인간의 예상보다 복잡한 일을 하기 때문에 그때그때 결과가 다를 수 있거든요.

brucewang의 이미지

아앗, 제 글로 인해 의도하지 않았던 방향으로 흘러 가게 되었군요. 죄송합니다.
단어싸움을 일으키거나 나이문제를 삼으려고 했던것이 아닙니다.
모두들 죄송합니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

체스맨의 이미지

C 표준이 string literal 은 static storage duration 을 갖는다고 정의하고 있으므로, 첫번째 함수는 타당합니다. static 으로 선언된 배열을 리턴하는 것과 다를 게 없죠.

단, char* 로 리턴하지 마시고, const char* 로 리턴하시는 것이 좋은 방법입니다.

두번째 함수가 잘 못 작동하는 것은 이미 아시는 것 같구요.

Orion Project : http://orionids.org

klyx의 이미지

질문 초점과는 좀 빗나가는데요, '둘다 쓰레기 값이 나와야 하지 않나요?'라는 부분에서 '쓰레기값이 나와야 한다'는 부분이 걸리네요.
댕글링포인터를 이용할때의 동작은 정의되지 않은 동작이기 때문에, 쓰레기값이 나온다는 보장도 없습니다.
쓰레기값조차 안나오고 그자리에서 죽어버려도 누구탓도 못하죠.

appler의 이미지

간만에 재미난 프로그래밍 얘기라..ㅎㅎ

정말 도움이 많이 되는군요...


laziness, impatience, hubris

不恥下問 - 진정으로 대화를 원하면 겸손하게 모르는 것은 모른다고 말하는 용기가 필요하다.


laziness, impatience, hubris

不恥下問 - 진정으로 대화를 원하면 겸손하게 모르는 것은 모른다고 말하는 용기가 필요하다.

정태영의 이미지

저런 식으로 return 을 하고 싶다면 char str 앞에 static 키워드를 사용해주세요.

static char *str = "...";
return str;

static char str[] = "...";
return str;

언제나 먹히는 방법이죠.

--
오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

rev7707의 이미지

다양한 시각에서 좋은 글들 감사합니다.

댓글 달기

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