1) 為什么我們要兩次向編譯器提供相同的資訊?2)不是多余的嗎?3)我們什么時候應該遵循這個規則?4)我們什么時候可以省略這個雙重宣告和定義?
void fx(void);
void fx ( void ){
printf("Hello World\n");
}
int main(void)
{
fx();
}
uj5u.com熱心網友回復:
在你的情況下,它是不需要的。
但在這種情況下:
double fx(double x);
int main(void)
{
printf("%f\n", fx(4.0));
printf("%f\n", dx(4.0));
}
double fx(double x)
{
return x * x;
}
double dx(double x)
{
return x * x;
}
<source>: In function 'main':
<source>:21:20: warning: implicit declaration of function 'dx'; did you mean 'fx'? [-Wimplicit-function-declaration]
21 | printf("%f\n", dx(4.0));
| ^~
| fx
<source>: At top level:
<source>:29:8: error: conflicting types for 'dx'; have 'double(double)'
29 | double dx(double x)
| ^~
<source>:21:20: note: previous implicit declaration of 'dx' with type 'int()'
21 | printf("%f\n", dx(4.0));
https://godbolt.org/z/6ffWf9xG8
通常,函式原型像
double fx(double);
1) 為什么我們要兩次向編譯器提供相同的資訊?
告訴編譯器代碼或庫函式中的某個地方fx已經或將要定義,它接受一個雙精度引數并回傳雙精度。編譯器可以發出正確的代碼來呼叫這個函式,傳遞引數并使用回傳值
2)不是多余的嗎
在你的例子中是這樣。如果在函式呼叫之前不知道函式的定義,則不是這樣。
- 我們什么時候應該遵循這個規則?
我在上面已經解釋過了。
- 我們什么時候可以省略這個雙重宣告和定義?
當函式在同一個編譯單元中定義并且在第一次呼叫之前定義在(作為.c檔案中的位置)之前。
uj5u.com熱心網友回復:
沒有主體的函式宣告,例如void fx(void);稱為原型,其目的是通知編譯器存在具有某種回傳型別、某種名稱和可選的某些引數集的函式,它可以期望在編譯期間在其他地方找到這些引數或之后何時鏈接。這些是語言的一部分,因為它們允許程式員模塊化設計他們的軟體。
宣告一個函式原型可以防止編譯器在你呼叫一個它還沒有看到定義的函式時抱怨,例如:
#include <stdio.h>
int foo(int in); //Without this the program will not compile
int main(){
printf("%d\n",foo(7));
}
int foo(int in){
return in 1;
}
此外,上面示例的第一行#include <stdio.h>告訴編譯器包含 C 標準 io 頭檔案。stdio.h包含一個原型,該原型告訴它一旦需要鏈接程式printf,它將能夠在表單中找到一個函式。int printf(const char*,...);
或者,您可以撰寫單獨的檔案“foo.c”、“foo.h”和“main.c”以獲得更模塊化的方法,如下所示:
主程式
#include <stdio.h>
#include "foo.h" //Include .h file to get prototype
int main(){
printf("%d\n",foo(7));
}
foo.h
#ifndef FOO_H
#define FOO_H
int foo(int in); //Prototype of foo()
#endif
foo.c
#include "foo.h"
int foo(int in){ //Declatation of foo()
return in 1;
}
然后你可以將 foo.c 編譯成一個目標檔案,并將它與 main.c 一起傳遞給編譯器,如下所示:
gcc -c foo.c
gcc -o main main.c foo.o
如果您不想使用原型,您不必強制使用原型,但如果您選擇不使用它們,您將需要在程式中宣告每個函式,然后再在另一個函式中呼叫它。
uj5u.com熱心網友回復:
1) 為什么我們要兩次向編譯器提供相同的資訊?
最初設計 C 時,計算機非常有限(例如,RAM 以 KiB 而非 MiB 或 GiB 為單位,單個 CPU 的時鐘小于 1 MHz,而不是多個 CPU 的時鐘大于 1 GHz,等等)。有很多技巧可以解決這個問題(將“編譯”拆分為多個階段,將“程式”拆分為多個編譯單元,以小塊讀取檔案,因此整個檔案不在 RAM 中,等等)。
其中一個技巧是一次性決議源檔案。這意味著如果您執行以下操作:
int foo(int x) {
return bar(x);
}
int bar(int x) {
return x;
}
..編譯器bar()在決議“ foo()”時不會知道“”是什么(因為它bar()直到稍后才會看到“”)。解決方案是宣告 - 允許程式員在定義之前宣告事物,因此編譯器可以執行一次傳遞,而不會被它尚未看到的事物弄糊涂。
- 我們什么時候可以省略這個雙重宣告和定義?
如果編譯器會在使用該定義之前看到該定義,則可以省略該宣告。例如,這會很好:
int bar(int x) {
return x;
}
int foo(int x) {
return bar(x);
}
2)不是多余的嗎?
這是多余的,但根據 C 語言規范是必要的,因為 50 多年前它是必要的(使編譯器在“資源極度受限”的計算機上實用);即使 30 多年以來它還沒有意義,而且更新的語言也不需要它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/519549.html
標籤:C功能海合会
上一篇:將輸入值與def函式一起使用
