char* str 과 char str[] 과의 차이점이 무엇입니까?
글쓴이: ultraman / 작성시간: 수, 2005/12/14 - 10:11오전
char* str = "abcd"; str[1] = 'x';
위와 같은 경우 Violation 에러가 나며, - 이게 에러나는 줄 처음(?)알았습니다. :roll:
char str[] = "abcd"; str[1] = 'x';
는 당연하게도 성공합니다.
단순히 문자배열과 char* 가 동일하다고 생각하고 있었는데...
위의 결과를 보면 완전히 다르군요.
이에 대한 차이점을 알고 싶습니다.
미리 답변에 감사드립니다. :D
Forums:
[url=http://www.cinsk.org/cfaqs/html/nod
C FAQ 6.2를 참고하기 바랍니다. 영문판은 여기에 있습니다.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
첨언하면 "abcd"는 변경이 불가능한 문자열 상수(string lite
첨언하면 "abcd"는 변경이 불가능한 문자열 상수(string literal)입니다. 그런데
char*가 이 문자열을 가리키게 하면 그 포인터를 통해 문자열을 바꾸는 실수를
해도 컴파일러는 아무런 에러 메시지를 내지 않지요. 따라서
와 같이 const로 한정하여 쓰는 것이 안전합니다.
두분 답변에 감사드립니다.덕분에 좋은 사이트도 알게되고, 통찰도
두분 답변에 감사드립니다.
덕분에 좋은 사이트도 알게되고, 통찰도 얻었습니다. :D
두분 답변을 토대로 정리하자면,
가 되지 않을까 합니다.
개발 시스템마다 틀립니다. 정확히는 컴파일러(링커)마다 다르다고해야
개발 시스템마다 틀립니다. 정확히는 컴파일러(링커)마다 다르다고
해야 합니다.
"abcd" 문자열이 .text 영역에 지정될 수 있고. .rodata 혹은 .data
영역에 지정될 수도 있습니다. objdump 나 elfdump 등으로
볼 수 있습니다.
위 코드를 SunOS 5.8, Sun Workshop 6 Update 1 C 5.2 로
컴파일 했을때와(이 경우에는 .data 영역에 지정), gcc 3.3.3 으로
했을때(.rodata 에 지정) 다릅니다.
---------
간디가 말한 우리를 파괴시키는 7가지 요소
첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스
이익추구를 위해서라면..
다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치
[quote="IsExist"]개발 시스템마다 틀립니다. 정확히는 컴파일
그런 것을 C에서는 "결과는 정의되지 않는다"고 말합니다.
이 코드를 실행한 결과가 어떻게 될 것인가에 대해서 표준은 어떤 보장도 하지 않고,
각 구현체에서 알아서 하라는 것이죠. 그 결과가 구현체마다 다른 것은 당연합니다.
C가 이식성을 추구하는 언어이고 의도한 결과를 얻을 수 있는 잘 정의된 방법을
제공하고 있기 때문에 이 코드는 잘못 되었다고 말하는 것입니다.
[quote]두분 답변을 토대로 정리하자면,인용:"abcd"가
틀렸습니다. str[1] = 'x'; 라는 수식 자체의 의미는, 위의 코드나 아래의 코드나 서로 다르지 않습니다.
일단 이런 코드가 있다고 칩시다.
str[1]은 코드 1이건 코드2이건 간에 *(str +1)이며 이것은 str +1 주소에 저장된 char형 그 자체를 뜻합니다. 코드 1과 코드 2의 차이는, str + 1이 가리키는 주소의 공간이 수정될 수 있는가 없는가 하는 점이며, 이때문에 코드 1에서는 문제가 발생하는 것입니다.
표준에서는 단지 문자열 상수(영어로 쓰면 string literal 이므로 '상수'라는 표현은 부정확하다고 볼 수도 있습니다. 토큰 상의 구분으로 볼때 constant와 string literal은 서로 별개입니다)를 수정할 때의 결과는 정의되지 않았다고 표현합니다. 새로 할당한다는 것도 오해의 여지가 있는 표현인데, 새로운 메모리가 할당되는 것이 아니라 기존의 이미 존재하는 공간의 데이터를 수정하는 행동이기 때문입니다.
코드 1과 코드 2의 차이점을 알기 위해서는 다음 사항들을 이해하고 있어야 합니다. 편의상 규칙 1,2,3,4라 이름을 붙이겠습니다.
1. 문자열 상수는 수정불가능한 char형 배열이다.
2. 배열은 그 자신의 첫번째 원소를 가리키는 포인터 주소값으로 자동 변환된다.
3. 2번에는 3가지 예외가 있는데, &연산자의 피연산자, sizeof 연산자의 피연산자, 그리고 char형 배열을 초기화할 때 쓰였을 경우이다.
4. array[2] 는 *(array+2)와 완전히 동일한 표현이다.
한가지 설명을 돕기 위한 예를 들어보이겠습니다.
위의 코드는 정상일까요? 정상입니다. str은 char형 배열 "abcd"의 첫번째 원소를 가리키는 주소값을 저장하게 됩니다.
위의 코드에서 "abcd"[2]는 *("abcd" + 2) 와 같은 뜻입니다. 그런데 "abcd"는 배열이며(규칙1), 그 자신의 첫번째 원소를 가리키는 포인터 주소값으로 자동 변환됩니다. 따라서 "abcd"[2]의 최종 결과값은 "abcd"란 배열의 세번째 원소(인덱스는 0이 첫번째이므로)인 'c'가 됩니다.
그럼 이제 코드 1과 2의 차이점에 대해 알아보겠습니다.
코드 1에서 char *str="abcd"; 의 의미는 char*형 변수 str에 문자열 상수(즉 배열) "abcd"의 첫번째 원소의 주소값을 기억하라는 뜻입니다(규칙2).
코드 2에서의 "abcd"는 코드 1에서의 "abcd"하고는 의미가 다르며, 일반적인 규칙과는 다른 규칙을 따릅니다(규칙 3을 상기하십시오). 문자열 상수가 char형 배열의 초기화에 쓰일 경우에는, 문자열 상수는 배열로 작용하는 것이 아니라 char형 배열을 초기화 하는데 쓰입니다. 따라서 코드 2에서는 크기 5의 char형 배열 str을 만들어서, 그 안에 'a', 'b', 'c', 'd', '\0' 이라는 내용을 저장하게 됩니다.
코드 1에서 문제가 생기는 이유는, C에서는 문자열 상수가 수정이 불가능(실제로는, 수정을 시도했을 시 그 결과는 정의되어 있지 않음)하기 때문이고, 코드 2에서 문제가 생기지 않는 이유는, char형 배열은 수정이 가능하기 때문입니다. str[1]이 가리키는 공간의 성격에 대해 유의할 필요가 있습니다.
참고로, 문자열 상수에는 한가지 재미있는 특성이 있습니다.
똑같은 내용의 문자열 상수라면, 컴파일러가 굳이 여러개의 배열을 만들지 않아도 됩니다. 즉, 위의 코드에서 출력되는 s1, s2, s3의 주소값이 동일할 수도 있습니다. 물론 아닐 수도 있고요.
댓글 달기