C 언어 기초

int get(int *p) {
    int v = *p;
    if (p == NULL)
        return -1;
    return v;
}

위의 함수를 gcc로 최적화를 켜고 컴파일하면 if (p == NULL)의 판정이 삭제되는 경우가 있다. 그 이유로 올바른 것은?

  1. A먼저 *p를 읽고 있으며, p가 NULL이면 거기서 미정의 동작이므로 p는 NULL이 아니라고 가정해도 되기 때문에
  2. BNULL과의 비교는 규격에서 항상 거짓이 된다고 정해져 있기 때문에
  3. C최적화에서는 함수의 인수를 조사하는 if 문은 호출한 쪽이 확인하는 것으로 간주되어, 모두 삭제해도 되는 규칙이기 때문에
정답과 해설 보기

정답: A. 먼저 *p를 읽고 있으며, p가 NULL이면 거기서 미정의 동작이므로 p는 NULL이 아니라고 가정해도 되기 때문에

p가 NULL이면 먼저 실행하는 int v = *p;가 NULL 포인터의 참조가 되며, 그 시점에서 미정의 동작입니다. 컴파일러는 미정의 동작이 일어나지 않는다고 가정해도 되므로, *p를 읽을 수 있었던 이상 p는 NULL이 아니라고 판단하여 p == NULL의 판정과 return -1을 제거합니다. x86-64의 gcc 13에서 -O2를 붙이면 함수는 *p를 읽어 반환할 뿐인 코드가 되고, -O0에서는 판정이 남습니다. 판정이 확실히 작동하게 하려면 *p를 읽기 전에 p를 확인합니다.

이 분야 연습하기 분야로 돌아가기

C 언어 기초의 다른 문제

  1. C 언어 규격에서 int형의 크기에 대해 정해져 있는 것으로 올바른 것은?
  2. 임베디드 프로그램에서 32비트 주변 장치 레지스터의 값을 넣는 변수를 unsigned int가 아니라 stdint.h의 uint32_t로 선언하는 경우가 많다. 주된 이유로 올바른 것은?
  3. 정수끼리의 나눗셈을 포함하는 위의 코드를 실행했을 때의 출력으로 올바른 것은?
  4. 전위와 후위 ++를 사용한 위의 코드를 실행했을 때의 출력으로 올바른 것은?
  5. if 문의 조건에 =를 쓴 위의 코드를 실행했을 때의 출력으로 올바른 것은?