2011-10-29 17 views
5

我知道的兩種可能的方式來定義和使用struct S:寫作結構代碼,無論是在C和C++中的工作

#1 
struct person 
{ 
    char name[32]; 
    int age; 
}; 

struct person dmr = {"Dennis Ritchie", 70}; 

#2 
typedef struct 
{ 
    char name[32]; 
    int age; 
} person; 

person dmr = {"Dennis Ritchie", 70}; 

的第一種方式的有趣的特性是,無論是類型和變量可以有相同的名稱:

struct person person = {"Sam Persson", 50}; 

這是C中的慣用嗎?它保證在C++中工作嗎?還是有我應該知道的角落案件?

請注意,我對純粹的C++答案不感興趣(例如「使用std::string而不是char[32]」)。這是一個關於C/C++兼容性的問題。

+0

我不會稱之爲「有趣的財產」,它是相當模糊的財產。最好從大寫開始保留類型名稱 - 區分類型名稱和變量名稱。 –

+0

我已經標記爲[typedef struct vs struct definitions](http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions)的重複。從技術上講,你可以認爲它不是(另一個問題只涉及C),但是C++中的語義與單一區別相同,即如果查找在用戶定義的標識符空間中找不到全局標識符空間。這也被接受的答案(包含C++的一部分) –

+1

也被視爲**而不是定義一個'不是名稱),還有'typedef's(可以應用於已命名或未命名的類型),但它們不是以任何速率定義'struct'的兩種方式。並且你錯過了3),結合了兩者:'typedef struct type {} type;'它值什麼(這是慣用的C方式) –

回答

1
struct person person = {"Sam Persson", 50}; 

對類型和變量使用相同的標識符不是地道的。在Unix中,通常使用變量名稱的縮寫版本,例如:struct stat st,struct timeval tv,...以相同的方式fd是文件描述符變量的典型名稱。

3

struct僅當它們是POD-s時才兼容C & C++。

我傾向於代碼是這樣的:

struct person_st { char name[32]; int age; }; 
typedef struct person_st Person_t; 
+2

那麼什麼是C的non-POD'struct'? – xanatos

+0

@xantos,'class'es!但不是'''你寫'結構'和成員默認是'public',而不是''''''''private'' – Shahbaz

+0

@Shahbaz:C中沒有類。我想這就是xanatos的含義。 – fredoverflow

0

我不知道這是否會在標準C++完全正確的,但我g++ -pedantic -Wall測試,並得到任何錯誤或警告(注意,這並未」這意味着它完全是標準的,g ++,即使是-pedantic,也沒有經歷給所有非標準代碼提供警告的麻煩。)(是否有人知道C++規範足以評論它是否實際是標準代碼? ?)

寫作東西:

struct person person = {...}; 

是在C++中,person都指向變量和類型。在C中,這不是一個簡單的問題,因爲person不是這個類型(struct person是)。儘管從上下文來看,通過使用g ++編寫的少量測試,編譯器在我詢問變量時以及對於該類型時理解沒有問題,但我認爲它可能會在某些時候感到困惑。我發現了一個令人困惑的事情是,如果您有:

struct person *person = ...; 

然後sizeof(person)返回變量的大小,而要獲得類型的大小,你應該寫sizeof(struct person),我可以向你保證,沒有C++程序員,會記得寫下stuct

最好避免各種混淆。我通常做這個代碼,可以在兩個C和C++使用:

typedef struct person 
{ 
    ... 
} person; 

給名字到被typedef版的結構允許程序員爲使用personstruct person。所以,有一點靈活性(更不用說你不必在typedefstruct之後改變已經寫好的代碼。

+1

對於'sizeof'示例。請參閱C++標準§9.1¶如果在聲明同名變量,函數或枚舉數的作用域中聲明瞭類名,則當兩個聲明都在作用域中時,該類只能使用elaborated-type-specifier_ – ninjalj

+0

不,在你的第一個例子C++中,'person'會引用這個變量。 –

2

我宣佈他們同時在結構標籤和全局標識符命名空間具有相同的名字:

#ifdef __cplusplus 
extern "C" { 
#endif 

typedef struct person 
{ 
    char name[32]; 
    int age; 
} person; 

#ifdef __cplusplus 
} 
#endif 

在使用時,需要在C和C++的翻譯沒有用的結構標籤:

person dmr = {"Dennis Ritchie", 70}; 

如果你喜歡某些地方的結構標籤,你也可以這樣使用它。

顯而易見的好處是,無論語言如何,這兩種名稱空間中的標識符都可以引用該類型。