[C/C++] printf("%s\n", NULL)/ (null) 출력 / segmentation fault
strtok
사용하기
오늘도 열심히 C언어 공부를 하던 중 흥미로운 사실을 발견해서 기록용으로 남겨놓는다. 문자열을 자르는 함수 strtok
을 이용하여 ' '
공백 문자 기준으로 잘라낸 다음 문자열 포인터에 잘라낸 문자열 주소를 저장한다. 그 다음 잘라낸 문자열들을 출력하는 예제이다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s1 = malloc(sizeof(char) * 30);
char *s2 = "The Little Prince";
strcpy(s1, s2);
char *sArr[10] = {
NULL,
}; // NULL로 배열 초기화
// 공백 문자 기준으로 잘라 sArr에 저장
char *ptr = strtok(s1, " ");
int ii = 0;
while (ptr != NULL)
{
sArr[ii] = ptr;
ii++;
ptr = strtok(NULL, " ");
}
// 저장된 문자열 출력
for (int jj = 0; jj < 10; jj++)
{
printf("%s\n", sArr[jj]);
}
free(s1);
return 0;
}
출력 결과
The
Little
Prince
정답과 다른데..😒
sArr
배열은 4번째 요소부터 10번째까지는 NULL
을 값으로 가지고 있지만 아무 문제 없이 출력되는 것을 확인할 수 있다. 그런데 원래 정답은 문자열 출력 부분이 다음과 같다.
...
for (int i = 0; i < 10; i++)
{
if (sArr[i] != NULL) // 문자열 포인터 배열의 요소가 NULL이 아닐 때만
printf("%s\n", sArr[i]); // 문자열 포인터 배열에 인덱스로 접근하여 각 문자열 출력
}
...
왜 여기서 sArr
의 요소가 NULL
이 아닌 경우에만 출력하는 것인지 궁금해서 여러 가지를 테스트해보았다. 예를 들면
printf(" %s\n", sArr[jj]);
printf("test%s\n", sArr[jj]);
와 같이 변경하여 컴파일하면 다음과 같이 출력된다.
The
Little
Prince
(null)
(null)
(null)
(null)
(null)
(null)
(null)
NULL
은 항상 주의
이것은 원래 printf
가 표준 입력, 즉 ANSI 코드만 받아들이기로 설게되어 있기 떄문에 그 외에 NULL
이 입력되는 경우는 Undefined behavior라 컴파일러마다 다른 행동을 보이게 된다.
PS C:\Users\user\Desktop\코딩공부해요\CC++> gcc --version
gcc.exe (MinGW.org GCC-6.3.0-1) 6.3.0
나는 gcc
를 사용하고 있기 때문에 위와 같이 행동하지만, 다른 컴파일러에서는 segmentation fault를 일으킨다. gcc
는 NULL
이 입력될 경우 puts()
함수를 호출하여 문제가 없이 실행된다.