考慮以下示例程式:
#include <stdio.h>
static int n = 123;
extern int n;
int main(void) { printf("n is %d\n", n); return 0; }
它與gcc -std=c99 -pedantic myprog.c
. n
根據 C99 § 6.2.2 Linkages of identifiers,第 4 部分具有靜態鏈接:
對于在該識別符號
extern
的先前宣告可見的范圍內使用存盤類說明符宣告的識別符號,如果先前宣告指定內部或外部鏈接,則后面宣告中識別符號的鏈接與指定的鏈接相同在之前的宣告中。如果沒有可見的先前宣告,或者如果先前宣告沒有指定鏈接,則識別符號具有外部鏈接。
現在洗掉extern
:
#include <stdio.h>
static int n = 123;
int n;
int main(void) { printf("n is %d\n", n); return 0; }
這個程式不能編譯。GCC 給出了這個錯誤:
myprog.c:4:5: error: non-static declaration of ‘n’ follows static declaration
4 | int n;
| ^
myprog.c:3:12: note: previous definition of ‘n’ was here
3 | static int n = 123;
|
為什么會出現這個錯誤?我認為int n;
第二個程式中的 應該相當于extern int n;
. 來自 C99 標準的 § 6.2.2 Linkages of identifiers,第 5 部分:
如果物件的識別符號宣告具有檔案范圍且沒有存盤類說明符,則其鏈接是外部的。
uj5u.com熱心網友回復:
您不能兩次宣告 n。靜態與否。
uj5u.com熱心網友回復:
您已經在標準中找到了相關部分。§4 說,如果你宣告它extern
并且已經宣告了一個內部鏈接變數,那么你的鏈接extern
也會變成內部的 - 所以它會參考同一個變數,就像你寫了static int n;
兩次一樣。
這些規則有點混亂,像這樣的古怪功能已經過時了。我不知道為什么它首先存在的歷史原因。
6.11.2 識別符號
的鏈接在沒有static
存盤類說明符的情況下在檔案范圍內宣告具有內部鏈接的識別符號是一個過時的功能。
在后一種情況下,您沒有指定鏈接,因此它是一個暫定定義。根據您在 §5 中參考的部分,它獲得外部鏈接,然后在同一翻譯單元中與內部鏈接識別符號發生命名沖突,因此出現編譯器錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/364668.html
下一篇:將變數恢復為其原始值