3. 포인터 매개변수를 배열로 표기한다. null이 될 수 없는 포인터는 항상 이렇게 표기한다. 예를 들면 다음과 같다.
/* 인수가 null이 될 수 없음을 강조한다. */ size_t strlen(char const string[static 1]); int main(int argc, char* argv[argc+1]); /* 위 함수를 다음과 같이 선언할 수도 있다. */ size_t strlen(const char *string); int main(int argc, char **argv);
첫 번째 문장은 strlen이 유효한 (null이 아닌) 포인터를 받고 string 원소를 최소한 한 개 받는다는 것을 강조한 것이다. 두 번째 문장은 main이 char에 대한 포인터로 구성된 배열을 받는다는 것을 표현한 것이다. 이 배열은 프로그램 이름과 프로그램 인수(argc-1)와 배열의 끝을 나타내는 null 포인터로 구성된다.
앞에 나온 그대로 네 문장을 모두 작성해도 문제없다. 세 번째와 네 번째 선언문은 이미 컴파일러가 아는 사실과 동일한 선언을 추가했을 뿐이다.
4. 함수 포인터 매개변수는 함수처럼 표기한다. 배열과 마찬가지로 함수 포인터도 null이 될 수 없을 때마다 이렇게 표현한다.
/* handler란 인수가 null이 될 수 없음을 강조한 표현 */ int atexit(void handler(void)); /* 같은 내용을 다르게 선언한 문장 */ int atexit(void (*handler)(void));
첫 번째 atexit 선언은 handler란 이름의 함수를 인수로 받으며 null 함수 포인터는 허용하지 않는다고 강조한 것이다. 참고로 배열 매개변수가 오브젝트 포인터로 변환되듯이, 함수 매개변수인 handler는 함수 포인터로 변환된다.
이 코드 역시 두 문장 모두 작성해도 문제없다. 두 번째 문장은 첫 번째 선언과 표현 방식이 다를 뿐이다.