Programing

C 및 C++에서 f()와 f(void)의 차이를 한 번, 그리고 전체적으로 이해

c10106 2022. 5. 24. 22:56
반응형

C 및 C++에서 f()와 f(void)의 차이를 한 번, 그리고 전체적으로 이해

좋아, 그래서 나는 이 주제에 대해 다른 의견을 들어봤고 내가 정확히 이해했는지 확인하고 싶어.

C++의 경우

선언void f();그리고void f(void);정확히 같은 것을 의미하는데,f매개 변수를 사용하지 마십시오.정의를 위한 디토.

C의 경우

void f(void);라는 뜻이다.f매개 변수를 사용하지 마십시오.

void f();그 함수를 의미한다.f매개변수가 있을 수도 있고 없을 수도 있으며, 매개변수가 있을 경우 매개변수의 종류 또는 개수를 알 수 없다.줄임표와 같지 않으므로 사용할 수 없음va_list.

이제 이곳이 흥미로운 곳이다.

사례 1

선언:

void f();

정의:

void f(int a, int b, float c)
{
   //...
}

사례 2

선언:

void f();

정의:

void f()
{
   //...
}

질문:.

사례 1과 2가 호출될 때 컴파일 시간에 발생하는 현상f올바른 주장, 잘못된 주장, 그리고 전혀 논쟁 없이?런타임에 무슨 일이 일어나는가?

추가 질문:

신고하면f하지만 그것들 없이 그것을 정의한다면, 그것이 변화를 만들 것인가?기능 본체의 주장을 설명할 수 있어야 하는가?

더 많은 용어(C++가 아닌 C): 함수의 프로토타입은 그 주장의 유형을 선언한다.그렇지 않으면 그 기능에는 프로토타입이 없다.

void f();                      // Declaration, but not a prototype
void f(void);                  // Declaration and prototype
void f(int a, int b, float c); // Declaration and prototype

프로토타입이 아닌 선언은 K&R C 시대부터 ANSI C 이전으로부터 보류된 것이다.구식 선언을 사용하는 유일한 이유는 구 코드와의 이진 호환성을 유지하기 위해서다.예를 들어, GTK 2에서는 프로토타입이 없는 함수 선언이 있다. 우연히 거기 있지만 바이너리를 깨지 않고는 제거할 수 없다.C99 표준 의견:

6.11.6 함수 선언기

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

권장 사항:모든 C 코드를 GCC/Clang에 컴파일할 것을 제안한다.-Wstrict-prototypes그리고-Wmissing-prototypes에, 시.에-Wall -Wextra.

무슨 일이 일어나는가

void f(); // declaration
void f(int a, int b, float c) { } // ERROR

선언문은 기능 본체에 동의하지 않는다!이것은 사실 컴파일 시간 오류인데, 이것은 당신이 그것을 가질 수 없기 때문이다.float원형이 없는 함수에서의 논쟁a를 사용할 수 없는 이유float형식화되지 않은 함수에서는 그러한 함수를 호출할 때 모든 주장이 특정 디폴트 프로모션을 사용하여 승격되기 때문이다.여기 고정된 예가 있다.

void f();

void g()
{
    char a;
    int b;
    float c;
    f(a, b, c);
}

이 프로그램에서는.a로 승진하다.int1 그리고c로 승진하다.double에 대한 정의는f()다음을 충족해야 함:

void f(int a, int b, double c)
{
    ...
}

C99 6.7.6 항목 15항을 참조한다.

한 형식에 매개 변수 유형 목록이 있고 다른 형식이 함수 정의의 일부가 아니며 빈 식별자 목록을 포함하는 함수 선언기에 의해 지정된 경우, 매개 변수 목록에는 줄임표 종단기가 없어야 하며 각 매개 변수의 유형은 채무불이행의 적용으로 인해 발생하는 유형과 호환되어야 한다.승진을 논하다

답 1

사례 1과 2가 호출될 때 컴파일 시간에 발생하는 현상f올바른 주장, 잘못된 주장, 그리고 전혀 논쟁 없이?런타임에 무슨 일이 일어나는가?

전화할 때f(), 매개 변수는 기본 프로모션을 사용하여 승격된다.승격된 유형이 에 대한 실제 매개 변수 유형과 일치하는 경우f(), 그러면 모든 것이 좋다.만약 그들이 일치하지 않는다면, 그것은 아마 컴파일 될 것이지만, 당신은 분명히 정의되지 않은 행동을 하게 될 것이다.

"정의되지 않은 행동"은 "우리는 무슨 일이 일어날지 보장하지 않는다"의 명제다.어쩌면 프로그램이 고장나거나, 잘 될 수도 있고, 시댁 식구들을 저녁 식사에 초대할 수도 있다.

컴파일 시간에 진단을 받는 방법에는 두 가지가 있다.교차모듈 정적 분석 기능을 갖춘 정교한 컴파일러가 있다면 아마도 오류 메시지가 나타날 것이다.또한 다음을 사용하여 GCC를 사용하여 프로토콜이 지정되지 않은 함수 선언에 대한 메시지를 받을 수 있다.-Wstrict-prototypes-- GTK 2를 사용하는 파일을 제외한 모든 프로젝트를 켜는 것이 좋다.

답안2

신고하면f하지만 그것들 없이 그것을 정의한다면, 그것이 변화를 만들 것인가?기능 본체의 주장을 설명할 수 있어야 하는가?

컴파일해서는 안 된다.

예외

함수 인수가 함수 정의에 동의하지 않을 수 있는 경우는 실제로 두 가지다.

  1. 합격해도 괜찮다.char *까지.void *그리고 역도 성립.

  2. 값이 두 가지 유형(즉, 음수가 아니며 서명된 유형의 범위를 벗어나지 않는 한)의 서명되지 않은 정수 유형을 해당 유형의 서명되지 않은 버전을 기대하는 함수 또는 그 반대로 전달하는 것은 괜찮다.

각주

1: 할 수 있다.char로 승격시키다.unsigned int그러나 이것은 매우 드문 일이다.

C99나 그 이상을 사용하고 있다면, 모든 것이 정말 무트 포인트다. (그리고, 오래된 임베디드 시스템이나 그와 같은 것에 갇혀 있지 않는 한, 당신은 아마도 좀 더 현대적인 것을 사용해야 할 이다.)

C99/C11 섹션6.11.6 Future language directions, Function declarators상태:

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

그러므로 당신은 다음과 같은 것들을 사용하는 것을 피해야 한다.void f();모두 합쳐서

매개 변수가 필요한 경우 적절한 프로토타입을 형성하여 나열하십시오.그렇지 않은 경우 사용void어떤 매개 변수를 필요로 하지 않는다는 것을 분명히 나타내기 위해서입니다.

C++에서는 f()와 f(void)가 같다.

C에서는 서로 다르고 f()함수를 호출하면서 얼마든지 논거를 전달할 수 있지만 f(void)로 논거를 전달할 수는 없다.

순수 C에서는 다음과 같은 오류가 발생한다.error C2084: function 'void __cdecl f(void )' already has a body

void f(void);
void f();

int main() {
  f(10);
  f(10.10);
  f("ten");

  return 0;
}

void f(void) {

}

void f() {

}

fvoid.c 라인(19) : 오류 C2084: 함수 'void _cdecl f(void )'는 이미 본문을 가지고 있다.

그러나 순수한 C++에서는 오류 없이 컴파일할 것이다.

과부하 기능(C++만 해당, C에는 과부하가 없음)

동일한 범위에서 f라는 이름으로 둘 이상의 함수를 선언하여 함수 이름 f를 과부하하는 경우.f의 선언은 인수 목록의 유형 및/또는 인수 수에 따라 서로 달라야 한다.f라는 이름의 과부하 함수를 부를 때는 함수 호출의 인수 목록과 과부하된 각 후보 함수의 매개변수 목록을 f라는 이름과 비교하여 올바른 함수를 선택한다.

예:

#include <iostream>
using namespace std;

void f(int i);
void f(double  f);
void f(char* c);


int main() {
  f(10);
  f(10.10);
  f("ten");

  return 0;
}

void f(int i) {
  cout << " Here is int " << i << endl;
}
void f(double  f) {
  cout << " Here is float " << f << endl;
}

void f(char* c) {
  cout << " Here is char* " << c << endl;
}

출력:

Here is int 10
Here is float 10.1
Here is char* ten

참조URL: https://stackoverflow.com/questions/13319492/understanding-the-difference-between-f-and-fvoid-in-c-and-c-once-and-for-a

반응형