programing

매개변수가 없는 함수(실제 함수 정의와 비교)는 왜 컴파일하는가?

prostudy 2022. 5. 9. 21:58
반응형

매개변수가 없는 함수(실제 함수 정의와 비교)는 왜 컴파일하는가?

나는 방금 왜 컴파일하는지 헷갈리는 누군가의 C코드를 우연히 발견했어.내가 이해할 수 없는 두 가지 점이 있다.

  1. 함수 프로토타입은 실제 함수 정의에 비해 매개변수가 없다.

  2. 함수 정의의 매개 변수에는 유형이 없다.


#include <stdio.h>

int func();

int func(param)
{
    return param;
}

int main()
{
    int bla = func(10);    
    printf("%d", bla);
}

이게 왜 효과가 있지?나는 그것을 컴파일러 두어 개에서 시험해 보았는데, 그것은 잘 작동한다.

int func();C표준이 없던 날, 즉 K&R C의 날(1989년 이전, 최초의 "ANSI C"표준이 발표된 해)부터의 모호한 함수 선언이다.

K&R C와 키워드에는 프로토타입이 없었다는 것을 기억하라.void아직 발명되지 않았다.컴파일러에게 함수의 반환 유형을 알려주는 것밖에 할 수 없었다.K&R C의 빈 매개변수 목록은 "지정되지 않았지만 고정된" 인수의 숫자를 의미한다.고정(fixed)이란, 매번 같은 수의 arg로 함수를 호출해야 한다는 것을 의미한다(예: 변량함수와 반대).printf각 통화마다 번호와 유형이 다를 수 있는 경우).

많은 컴파일러들이 특히 이 구조를 진단할 것이다.gcc -Wstrict-prototypes기능 선언은 프로토타입처럼 보이지만(특히 C++에 의해 중독된 경우) 그렇지 않기 때문에 즉석인 "기능 선언은 프로토타입이 아니다"라고 말할 것이다.구식 K&R C 복귀형 선언이다.

경험치:빈 매개 변수 목록 선언을 비워 두지 마십시오. 사용int func(void)例句】로 K이로써 K&R 리턴형 선언은 적절한 C89 프로토타입으로 바뀐다.컴파일러는 행복하고, 개발자는 행복하고, 정적 체커는 행복하다.그러나 C+++에 의해 잘못 이끌리는 사람들은 외국어 능력을 발휘하려고 할 때 추가 문자를 입력해야 하기 때문에 움츠러들 수 있다:-)

다른 답은 모두 맞지만, 단지 완성을 위해서입니다.

함수는 다음과 같은 방법으로 선언된다.

  return-type function-name(parameter-list,...) { body... }

return-type은 함수가 반환하는 변수 유형이다.배열 형식이나 함수 형식일 수 없다.주어지지 않으면, int를 가정한다.

함수 이름은 함수의 이름이다.

매개 변수 리스트는 함수가 쉼표로 구분하여 사용하는 매개 변수 목록이다.매개변수가 지정되지 않은 경우, 함수는 어떤 매개변수를 사용하지 않으며 빈 괄호 집합 또는 키워드 공백으로 정의해야 한다. 매개변수 목록의 변수 앞에 변수 유형이 없는 경우 int가정한다.배열과 함수는 함수에 전달되지 않고 자동으로 포인터로 변환된다.목록이 줄임표(,...)로 종료되면 설정된 파라미터 수가 없다.참고: 줄임표를 사용할 때 헤더 stdarg.h를 사용하여 인수에 액세스할 수 있다.

그리고 또 다시 완전성을 위해서.C11 규격 6:11:6부터 (179페이지)

빈 괄호(시제품 형식 매개변수 형식 선언기가 아님)가 있는 함수 선언기의 사용모호한 기능이다.

주식회사func()어떤 수의 논쟁도 통과시킬 수 있다는 것을 의미한다.인수를 원하지 않으면 다음과 같이 선언해야 한다.func(void). 함수에 전달할 유형(지정되지 않은 경우)은 기본값:int.

K&R 스타일 함수 선언과 정의야.C99 Standard(ISO/IEC 9899:TC3)

섹션 6.7.5.3 기능 해제기(시제품 포함)

식별자 목록은 함수의 매개 변수에 대한 식별자만 선언한다.함수의 정의에 속하는 함수 선언기의 빈 목록은 함수에 매개 변수가 없음을 지정한다.함수의 정의에 포함되지 않는 함수 선언기의 빈 목록은 매개변수의 수 또는 유형에 대한 정보가 제공되지 않음을 명시한다. (두 기능 유형이 모두 "구형"인 경우 매개변수 유형은 비교되지 않는다.)

6.11.6 기능 선언기

빈 괄호(시제품 형식 매개변수 형식 선언기가 아님)가 있는 함수 선언기의 사용은 모호한 기능이다.

섹션 6.11.7 기능 정의

별도의 매개변수 식별자 및 선언 목록(시제품 형식 매개변수 유형 및 식별자 선언자가 아님)과 함께 함수 정의를 사용하는 것은 노후화된 기능이다.

옛날 스타일은 K&R 스타일을 의미해.

예:

선언:int old_style();

정의:

int old_style(a, b)
    int a; 
    int b;
{
     /* something to do */
}

@Krishnabhadra에서 말한 바와 같이, 다른 이용자들의 이전의 모든 반응은 정확한 해석을 가지고 있으며, 다만 일부 사항에 대해서는 좀 더 상세한 분석을 하고 싶을 뿐이다.

ANSI-C에서와 같은 구-C에서 "형식되지 않은 형식 매개변수"에서 8비트 MPU에서 작업 레지스터 또는 명령 깊이 역량(그림자 레지스터 또는 명령 누적 주기)을 디멘션하면 16비트 MPU에서 int16이 되고 64비트 아키텍처가 -m32와 같은 옵션을 컴파일하도록 선택할 수 있는 경우 int16이 된다.

높은 수준에서 구현하는 것이 더 간단해 보이지만, 제어 디멘시온 데이터 유형 단계에서 프로그래머의 작업인 다중 매개변수 통과는 더 까다로워진다.

다른 경우, 일부 마이크로프로세서 아키텍처의 경우, ANSI 컴파일러는 코드 사용을 최적화하기 위해 이 오래된 기능들 중 일부를 활용하고, 이러한 "유형화되지 않은 형식 매개변수"의 위치가 작업 레지스터 내부 또는 외부에서 작동하도록 강요했으며, 오늘날에는 "휘발성"과 "등록"의 사용과 거의 동일한 결과를 얻을 수 있다.

그러나 가장 현대적인 컴파일러는 두 가지 유형의 매개변수 선언을 구별해서는 안 된다는 점에 유의해야 한다.

Linux에서 gcc를 사용한 컴파일의 예:

본시

main2.c.

main3.c.  
어떤 경우든 프로토타입에 대한 매개변수 참조가 없는 호출은 없기 때문에 현지에서는 프로토타입의 문구를 사용할 수 없다.시스템을 "유형화되지 않은 형식 매개 변수"와 함께 사용하는 경우 외부 호출에 대해 선언형 프로토타입 데이터 유형을 생성하십시오.

다음과 같은 경우:

int myfunc(int param);

C는 함수 반환 유형매개 변수 목록에 유형이 지정되지 않은 것으로 가정한다.이 규칙만이 이상한 것들을 따르는 것이 가능하다.

함수 정의는 다음과 같다.

int func(int param) { /* body */}

만약 당신이 쓴 프로토타입이라면

int func(int param);

프로토타입에서는 파라미터 유형만 지정할 수 있다.매개 변수의 이름은 필수 사항이 아니다.그렇게

int func(int);

매개 변수 유형을 지정하지 않고 이름을 지정하는 경우에도int유형으로 가정한다.

int func(param);

더 멀리 가면, 뒤따르는 것도 효과가 있다.

func();

컴파일러 가정int func()글을 쓸 때func()하지만 말하지마.func()기능 본체 내부에함수 호출이 될 겁니다.

  • 빈 매개 변수 목록은 "모든 인수"를 의미하므로 정의가 틀린 것은 아니다.
  • 누락된 유형은 다음과 같은 것으로 가정한다.int.

나는 이것을 통과하는 어떤 빌드도 구성된 경고/오류 레벨에서 부족하다고 생각하지만, 이것이 실제 코드를 허용하는 것은 의미가 없다.

매개변수 유형에 대해서는 이미 정답을 입력했지만 컴파일러에서 정답을 듣고 싶다면 플래그를 추가해 보십시오(플래그는 거의 항상 좋은 아이디어임).

프로그램을 컴파일하여gcc foo.c -Wextra알겠다:

foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]

기이-Wextra을 위해 이것을 알아채지 못하다.clang(인식되지 않음)-Wmissing-parameter-type어떤 이유로, 아마도 위에서 언급된 역사적인 것 때문에) 그러나-pedantic다음 작업을 수행하십시오.

foo.c:5:10: warning: parameter 'param' was not declared, 
defaulting to type 'int' [-pedantic]
int func(param)
         ^
1 warning generated.

그리고 위에서 다시 말한 프로토타입 문제에 대해서.int func()임의로 정의하지 않는 한 임의 매개 변수를 가리킴int func(void)그러면 예상대로 오류가 발생할 수 있다.

foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here

또는 안에clang다음과 같이.

foo.c:5:5: error: conflicting types for 'func'
int func(param)
    ^
foo.c:3:5: note: previous declaration is here
int func(void);
    ^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
    int bla = func(10);
              ~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.

함수 선언에 매개 변수가 없는 경우(예: 비어 있는 경우) 지정되지 않은 수의 인수를 사용하는 것이다.인수를 사용하지 않도록 하려면 다음 항목으로 변경하십시오.

int func(void);

이것이 내가 일반적으로 사람들에게 그들의 코드를 다음과 같이 컴파일하라고 조언하는 이유다.

cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition

이 깃발은 다음과 같은 몇 가지를 강요한다.

  • -누락-변수-선언:시제품을 먼저 구하지 않고서는 정전기 기능을 선언할 수 없다.따라서 헤더 파일의 프로토타입이 실제 정의와 일치할 가능성이 더 높아진다.또는 공개적으로 볼 필요가 없는 기능에 정적 키워드를 추가하도록 강제한다.
  • -Wstrigital-선언:프로토타입은 인수를 적절히 나열해야 한다.
  • -Wold-style-definition:함수 정의 자체도 인수를 적절하게 나열해야 한다.

이러한 플래그는 많은 오픈 소스 프로젝트에서도 기본적으로 사용된다.예를 들어, FreeBSD는 Makefile에서 WARCH=6으로 빌드할 때 이러한 플래그를 활성화한다.

구식 선언기에서는

함수 정의의 머리(Par.A.10.1)에서 선언기를 사용하지 않는 한 식별자 목록이 없어야 한다.매개변수 유형에 대한 정보는 선언서에 의해 제공되지 않는다.예를 들어 선언문

int f(), *fpi(), (*pfi)();

정수를 반환하는 함수 f, 정수에 포인터를 반환하는 함수 fpi, >정수를 반환하는 함수에 포인터 pfi를 선언한다.이들 중 어느 것도 >지정된 파라미터 타입은 없으며, 구식이다.

신식 선언서

int strcpy(char *dest, const char *source), rand(void);

strcpy는 int를 반환하는 함수로서, 첫 번째 변수인 두 번째 변수, 그리고 두 번째 변수인 상수 문자에 대한 포인터가 있다.

출처:- K&R 도서

네 의심이 풀렸으면 좋겠는데..

참조URL: https://stackoverflow.com/questions/13950642/why-does-a-function-with-no-parameters-compared-to-the-actual-function-definiti

반응형