我是 C 新手,遇到一個很困惑的現象。這是代碼片段:
// hello.c
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello, %s!\n", getlogin());
}
當我使用cc hello.c編譯它時,我會收到一條警告訊息,并且運行./a.out會導致段錯誤。
像這樣:
client@ubuntu:01$ cc hello.c
hello.c: In function ‘main’:
hello.c:5:26: warning: implicit declaration of function ‘getlogin’ [-Wimplicit-function-declaration]
5 | printf("Hello, %s!\n", getlogin());
| ^~~~~~~~
hello.c:5:19: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
5 | printf("Hello, %s!\n", getlogin());
| ~^ ~~~~~~~~~~
| | |
| char * int
| %d
client@ubuntu:01$ ./a.out
Segmentation fault (core dumped)
但是這兩種方法可以解決這個問題:這是第一種方法
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("Hello, %s!\n", getlogin());
}
這是第二種方法:
#include <stdio.h>
char * getlogin();
int main(int argc, char **argv) {
printf("Hello, %s!\n", getlogin());
}
我可以理解第一個解決方案,但為什么第二個解決方案可以作業?謝謝,我的朋友。
uj5u.com熱心網友回復:
使用第二種解決方案,目標檔案將被編譯,因為提供了函式的宣告,并且對該函式的呼叫與該宣告兼容。
默認情況下,大多數編譯器會將程式鏈接到該平臺上的標準 C 庫。聯結器將getlogin在該庫中找到該符號并使用它。因此也滿足連接器。
以下程式有效(并且什么也不做):
char *getlogin(void);
int main(void)
{
(void) getlogin();
}
現在,當您使用普通引數編譯它時,它很可能會正常作業。
但是,如果你通過-nostdlib或使用任何方法編譯器可以使用,以避免鏈接到標準庫,它不作業,聯結器應該抱怨。例如:
undefined reference to `getlogin'
uj5u.com熱心網友回復:
C 現在是一種相當古老的語言:它是在 70 年代創建的,作為構建 Unix 內核的工具。雖然進化了很多,但還是有老老實實當老大,守規矩的地方。函式宣告是其中之一:
- 外部函式(將在鏈接時決議)必須在編譯單元中宣告,并且必須提供給聯結器。這兩個操作是完全獨立的(如果鏈接的函式和宣告的函式不一樣,這通常會導致崩潰......)
- 如果一個函式在沒有宣告的情況下使用,它只是應該回傳一個
int值并且不給出預期引數的指示(這里缺少的宣告被視為int getlogin())。
其基本原理是,如果懶惰的程式員確保始終傳遞正確的引數,則他們可以跳過函式宣告。
那是背景關系,接下來是您的問題的答案:標準庫的包含檔案只不過是一組宣告。并且由于#include指令僅包含外部檔案的文本,包括編譯單元中的頭檔案,或者手動鍵入宣告在編譯器的角度上是嚴格等效的。
這并不意味著您可以采用任何一種方式。包含頭檔案可以保證您始終使用正確的宣告,而在所有編譯單元中手動添加宣告會增加拼寫錯誤的風險,并且會使維護更加困難,因為宣告分散在大量檔案中而不是干凈的并且很好地集中在一個地方。
uj5u.com熱心網友回復:
宣告是向編譯器提供有關變數型別或函式的資訊,在您的情況下,向編譯器提供有關函式回傳型別及其引數的資訊
在使用任何標準函式之前,我們必須檢查它們的宣告(必須與頭檔案中宣告的相同)以避免此類警告,否則我們需要包含包含這些宣告的頭檔案。
并且getlogin()不推薦使用 getlogin() c函式回傳NULL并報錯“No such file or directory”
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/382565.html
標籤:C
上一篇:我在c中的常量概念有問題
下一篇:在C中搜索陣列
