2010-09-25 147 views
15

here報價,瞭解ç命名空間

在C,有類型的兩個不同的命名空間:結構/聯合/枚舉標記名稱的命名空間和typedef名稱的命名空間。

name.c

$ cat name.c 
#include<stdio.h> 

typedef long long long2; 

int long2() { 
    return 4; 
} 

int main() { 

    printf("hello, world!"); 
    return 0; 
} 
$ gcc name.c -o name 
name.c:4: error: 'long2' redeclared as different kind of symbol 
name.c:3: error: previous declaration of 'long2' was here 
$ 

name2.c

$ cat name2.c 
#include<stdio.h> 

int four() { 
    return 4; 
} 

struct dummy { 
    int member; 
}; 

int main() { 

    struct dummy four; 
} 

$ gcc name2.c -o name2 
$ 

我想了解Ç命名空間衝突。

  • 在第一種情況下,爲什麼會出現衝突?函數是否也屬於typedef命名空間?

  • 在第二種情況下,爲什麼沒有衝突呢?函數和變量都被命名爲四。爲什麼編譯器允許這樣做? &four應該如何解決?

回答

20

C有四個不同的名字空間標識符:

  • 標籤的名稱(goto型)。
  • 標籤(結構,工會和枚舉的名稱)。
  • 結構和聯合的成員(每個結構/聯合都有單獨的名稱空間)。
  • 所有其他標識符(函數名稱,對象名稱,類型(def)名稱,枚舉常量等)。

另請參閱C99 6.2.3。

  1. 是,函數名和typedef名稱共享相同的命名空間:

    所以你的兩個問題可以作爲回答。

  2. 沒有衝突,因爲編譯器將使用作用域規則(用於函數或對象名稱)。主標識符稱爲shadow全局函數名稱,如果將警告級別設置得足夠高,則編譯器會警告您。
+0

結構/聯合/枚舉是否共享一個名稱空間?也就是說'struct T'和'union T'能夠很好的結合在一起嗎? – iBug 2017-11-17 10:00:03

5

你的第二個例子不顯示「沒有衝突」。有衝突!試試這個:

#include <stdio.h> 
int four(void) { return 4; } 
struct dummy { int member; }; 
int main(void) { 
    struct dummy four; 
    four.member = four(); 
} 

現在這個

#include <stdio.h> 
int four(void) { return 4; } 
struct dummy { int member; }; 
int main(void) { 
    int (*fx)(void) = four; /* "save" function */ 
    struct dummy four;  /* hide it   */ 
    four.member = fx(); /* use "hidden" fx */ 
} 

在你的第二個例子中,變量four功能four()

6

但是,您的示例中的關鍵點不是關於名稱空間,而是名稱的範圍。

name.c,既long2是「普通的標識符」(共享相同的命名空間),且二者在同一範圍內定義,因此有衝突。 (C99 § 6.7/3)

如果name2.c,局部變量four在比功能four深的範圍,所以可變獸皮功能four(C99 § 6.2.1/4) 。