저는 비교적 C를 처음 접했습니다. 전에 본 적이없는 함수 구문의 한 형태를 보았습니다. 여기서 매개 변수 유형은 해당 매개 변수 목록 뒤에 정의됩니다. 누군가가 일반적인 C 함수 구문과 어떻게 다른지 설명해 줄 수 있습니까?
예:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
답변:
이것이 여전히 지원되는 매개 변수 목록의 이전 스타일 구문입니다. K & R C에서는 유형 선언을 생략 할 수도 있으며 기본값은 int입니다. 즉
main(argc, argv)
char *argv[];
{
return 0;
}
동일한 기능이 될 것입니다.
int
으므로 명시 적으로 선언해야합니다.
또한 흥미로운 점은 프로토 타입이없는 함수와 함수의 호출 규칙 차이입니다. 이전 스타일 정의를 고려하십시오.
void f(a)
float a; {
/* ... */
}
이 경우 호출 규칙은 모든 인수가 함수에 전달되기 전에 승격된다는 것입니다 (예 : float
인수는 double
전달되기 전에 먼저로 승격됩니다 ). 따라서 f
a를 수신 double
했지만 매개 변수에 유형 float
(완벽하게 유효한)이있는 경우 컴파일러는 함수의 본문을 실행하기 전에 double을 float로 변환하는 코드를 내 보내야합니다.
프로토 타입을 포함하면 컴파일러는 더 이상 자동 승격을 수행하지 않으며 전달 된 모든 데이터는 마치 할당에 의해 프로토 타입의 매개 변수 유형으로 변환됩니다. 따라서 다음은 합법적이지 않으며 정의되지 않은 동작이 발생합니다.
void f(float a);
void f(a)
float a; {
}
이 경우 함수의 정의는 정의가 구식이기 때문에 제출 된 매개 변수를 double
(승격 된 양식) 에서로 변환합니다 float
. 그러나 함수에 프로토 타입이 있기 때문에 매개 변수는 부동 소수점으로 제출되었습니다. 예를 들어, clang은
main.c : 3 : 9 : 경고 : K & R 함수 매개 변수의 승격 된 유형 'double'이 이전 프로토 타입에서 선언 된 매개 변수 유형 'float'와 호환되지 않습니다. [-Wknr-promoted-parameter]
모순을 해결하는 옵션은 다음 두 가지입니다.
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
선택권이 있다면 옵션 2를 선호해야합니다. 이전 스타일 정의를 제거하기 때문입니다. 함수에 대해 이와 같이 모순되는 함수 유형이 동일한 번역 단위에 나타나면 컴파일러는 일반적으로 알려줍니다 (필수는 아님). 이러한 모순이 여러 번역 단위에 나타나는 경우 오류가 눈에 띄지 않게되어 버그를 예측하기 어려울 수 있습니다. 이러한 오래된 스타일 정의를 피하는 것이 가장 좋습니다.
차이가 없습니다. 단지 그것이 C에서 함수 선언을위한 오래된 구문이라는 것입니다. ANSI 이전에 사용되었습니다. 80 년대의 친구들에게 줄 계획이 아니라면 그런 코드를 작성하지 마십시오 . 또한 암시 적 유형 가정에 의존하지 마십시오 (다른 답변이 제안하는 것처럼)
함수 정의에 대한 이전 구문은 여전히 작동하지만 (컴파일러에게 요청하면 경고와 함께) 함수 프로토 타입을 제공하지 않습니다.
함수 프로토 타입이 없으면 컴파일러는 함수가 올바르게 호출되었는지 확인하지 않습니다.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
프로그램이 실행되면 내 컴퓨터의 출력은 다음과 같습니다.
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
늙었 든 아니든, 나는 낡은 것이 무엇이고 어떤 것이 .. 피라미드와 같은 고대인지 논쟁 할 것입니다. 그러나 오늘날의 과학자 중 어느 누구도 그것이 어떻게 만들어 졌는지 단서가 없습니다. 되돌아 보면, 오래된 프로그램은 오늘날에도 메모리 누수없이 작동하지만 이러한 "새로운"프로그램은 더 자주 실패하는 경향이 있습니다. 여기에 트렌드가 보입니다.
아마도 그들은 함수를 실행 가능한 본문을 가진 구조체로 보았다. 수수께끼를 풀기 위해서는 ASM에 대한 지식이 필요합니다.
편집, 인수 이름을 전혀 제공 할 필요가 없음을 나타내는 매크로를 찾았습니다.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
다음은 사용 예입니다. library는 zlib-1.2.11 입니다.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
그래서 두 번째 추측은 함수 오버로딩에 대한 것입니다. 그렇지 않으면 이러한 인수가 사용되지 않았습니다. 하나의 구체적인 기능, 이제 동일한 이름을 가진 무한한 양의 기능.