단순히 printf()로 이 둘을 찍어보았을 때 차이는 없다. 하지만 둘은 선언되는 데이터 타입이 다르다.
char *variable
로 선언된 str0
는 char 타입 포인터에 상수문자열을 할당한 것이다. 따라서 상수인 읽기전용 데이터로 선언되었고, 이는 스텍 영역이 아닌 데이터 영역에 그 값이 저장되어있다는 것을 의미한다. 이에 문자 값의 변경이 불가능하다.
char variable[]
로 선언된 str1
의 경우에는 문자들로 이루어진 단일 배열이다. 위의 경우와는 달리 스텍에 저장되어 있고, 따라서 값의 변경이 가능하다.
// ...
int main(void) {
char str1[] = "Hello World";
str1[2] = 'D';
printf("%s\n", str1); // "HeDlo World"; 출력
return 0;
}
따라서 둘은 사이즈도 다르다. 저수준 입출력 등 일부 함수에서 해당 변수의 사이즈를 parameter로 요구하는 경우도 있는데, 이 때 둘을 혼동하지 않고 잘 구분해서 써야한다. char variable[]
로 선언된 문자열에 sizeof()
매크로를 활용하면 문자열 전체의 길이를 가져올 수 있지만, char *variable
는 그러지 못하고 포인터 자료형인 int의 자료형 크기만 가져오기 때문이다.
#include <unistd.h>
// fd, 문자열 주소와 사이즈를 받고 write로 출력하고 개행문자를 출력하는 함수
void write_endl(int fd, char const *str, size_t len) {
write(fd, str, len);
write(fd, "\n", 1);
}
int main(void) {
char *str0 = "Hello World";
char str1[] = "Hello World";
// sizeof(str0)는 8, 'Hello Wo' 까지만 출력이 된다.
write_endl(STDOUT_FILENO, str0, sizeof(str0));
// sizeof(str1)은 12, 'Hello World' 모두 잘 출력이 된다.
write_endl(STDOUT_FILENO, str1, sizeof(str1));
return 0;
}
TCP/IP 소켓 프로그래밍 예제를 학습하다가, 둘의 차이점이 없는 줄 알고 혼동하여 썼었다. 이를 해결하기 위해 포인터로 선언했을 때는 strlen()
함수 등을 통해 정확한 길이를 확인한 후 출력했다.
#include <unistd.h>
#include <string.h>
void write_endl(int fd, char const *str, size_t len) {
write(fd, str, len);
write(fd, "\n", 1);
}
int main(void) {
char *str0 = "Hello World";
// 잘 출력이 되는 것을 확인할 수 있다.
write_endl(STDOUT_FILENO, str0, strlen(str0));
return 0;
}