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
로 승진하다.int
1 그리고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
하지만 그것들 없이 그것을 정의한다면, 그것이 변화를 만들 것인가?기능 본체의 주장을 설명할 수 있어야 하는가?
컴파일해서는 안 된다.
예외
함수 인수가 함수 정의에 동의하지 않을 수 있는 경우는 실제로 두 가지다.
합격해도 괜찮다.
char *
까지.void *
그리고 역도 성립.값이 두 가지 유형(즉, 음수가 아니며 서명된 유형의 범위를 벗어나지 않는 한)의 서명되지 않은 정수 유형을 해당 유형의 서명되지 않은 버전을 기대하는 함수 또는 그 반대로 전달하는 것은 괜찮다.
각주
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
'Programing' 카테고리의 다른 글
Vue.JS - '역사' 및 '추상' 라우터 둘 다? (0) | 2022.05.24 |
---|---|
Vue.js에서 사용자 지정 렌더 기능이 있는 텍스트 노드 생성 (0) | 2022.05.24 |
vuex에 저장된 공리에서 response.data 정의되지 않음 가져오기 (0) | 2022.05.24 |
Vuex 글로벌 상태 변경이 Nuxt의 v-for 루프에서 리렌더 구성 요소를 트리거하지 않음 (0) | 2022.05.24 |
java.net.URLEncoder.encode(스트링)가 더 이상 사용되지 않는데, 그 대신 무엇을 사용해야 하는가? (0) | 2022.05.24 |