왜 gcc는 인수가 없도록 정의 된 함수에 인수를 전달할 수 있습니까?


1 Answers

레거시 이유로, 매개 변수 목록에 대해 () 를 사용하여 함수를 선언한다는 것은 "함수가 호출 될 때 매개 변수를 찾아내는"것을 의미합니다. 함수에 매개 변수가 없도록 지정하려면 (void) .

편집 : 나는이 문제에 대한 평판이 오래되었다고 생각합니다. 그냥 아이들이 어떤 프로그래밍을 사용했는지 알고 있습니다. 여기 제 첫 번째 프로그램이 있습니다. (C가 아닌, 이전에 작업 한 내용을 보여줍니다.)

Question

나는 왜이 코드를 컴파일하지 않는가?

#include <stdio.h>
void foo() {
    printf("Hello\n");
}

int main() {
    const char *str = "bar";
    foo(str);
    return 0;
}

gcc는 foo ()에 너무 많은 인수를 전달한다는 경고를 던지지 않습니다. 이 예상되는 동작입니까?




C99 표준 (6.7.5.3) 및 C11 표준 (6.7.6.3) 상태 :

식별자 목록은 함수 매개 변수의 식별자 만 선언합니다. 해당 함수 정의의 일부인 함수 선언자의 빈 목록은 함수에 매개 변수가 없음을 나타냅니다. 해당 함수 정의의 일부가 아닌 함수 선언자의 빈 목록은 매개 변수의 수 또는 유형에 대한 정보가 제공되지 않음을 지정합니다.

foo의 선언은 정의의 일부이기 때문에 선언은 foo가 0 개의 인수를 취하도록 지정하므로 foo (str) 호출은 적어도 도덕적으로 잘못되었습니다. 그러나 아래에서 설명하는 것처럼 C에는 "잘못된"정도가 다르며 컴파일러는 특정 종류의 "잘못된"문제를 처리하는 방법이 다를 수 있습니다.

약간 더 간단한 예제를 사용하려면 다음 프로그램을 고려하십시오.

int f() { return 9; }
int main() {
  return f(1);
}

만약 내가 위의 Clang을 사용하여 컴파일 :

tmp$ cc tmp3.c
tmp3.c:4:13: warning: too many arguments in call to 'f'
  return f(1);
         ~  ^
1 warning generated.

gcc 4.8로 컴파일하면 -Wall을 사용하더라도 오류나 경고가 발생하지 않습니다. 이전 답변은 -Wstrict-prototype을 사용하여 제안했는데, 이는 f의 정의가 프로토 타입 형식이 아니라고 정확하게보고하지만 실제로는 그렇지 않습니다. C 표준은 위와 같은 프로토 타입이 아닌 형식의 함수 정의를 허용하며 표준은이 정의가 함수가 0 개의 인수를 취하도록 지정합니다.

이제 제약 조건이 있습니다 (C11 Sec. 6.5.2.2).

호출 된 함수를 나타내는식이 프로토 타입을 포함하는 형식 인 경우 인수의 수는 매개 변수의 수와 일치해야합니다.

그러나 함수의 유형에 프로토 타입이 포함되어 있지 않으므로이 제약 조건은 적용되지 않습니다. 그러나 의미 영역 ( "제약 조건"이 아닌)에 다음 문장이 적용됩니다.

호출 된 함수를 나타내는식이 프로토 타입을 포함하지 않는 형식 인 경우 ... 인수의 수가 매개 변수의 수와 같지 않으면 동작은 정의되지 않습니다.

따라서 함수 호출은 정의되지 않은 동작을 발생시킵니다 (즉, 프로그램이 "엄격하게 준수"하지 않음). 그러나이 표준은 실제 제약이 위반 될 때 진단 메시지를보고하기위한 구현만을 요구하며,이 경우 제약에 대한 위반은 없다. 따라서 gcc는 "준수 구현"을 위해 오류나 경고를보고 할 필요가 없습니다.

그래서 나는 질문에 대한 대답, 왜 gcc는 그것을 허락합니까?, 이것은 제약 위반이 아니기 때문에 gcc가 아무것도보고하지 않아도된다는 것입니다. 게다가 gcc는 -Wall 또는 -Wpedantic을 사용하더라도 모든 종류의 정의되지 않은 동작을보고한다고 주장하지 않습니다. 이것은 정의되지 않은 동작입니다. 즉, 구현이이를 처리하는 방법을 선택할 수 있으며 gcc는 경고없이 컴파일하도록 선택했습니다 (그리고 명백히 인수를 무시합니다).




Related