2017-06-29 17 views
2

關於this關於某個Winsock結構的頁面,這個例子看起來像是取了一個結構體的地址,並將結果指針轉換爲指向完全不同結構的指針。C++嚴格別名:不是這個MSFT示例UB嗎?

SOCKET ListenSocket; 
struct sockaddr_in saServer; 
// Bind the listening socket using the information in the sockaddr structure 
bind(ListenSocket,(SOCKADDR*) &saServer, sizeof(saServer)); 

下面是這兩個結構的聲明。這在技術上是未定義的行爲,對嗎?

struct sockaddr { 
     ushort sa_family; 
     char sa_data[14]; 
}; 

struct sockaddr_in { 
     short sin_family; 
     u_short sin_port; 
     struct in_addr sin_addr; 
     char sin_zero[8]; 
}; 
+0

指針轉換從不違反嚴格的別名規則(看起來這是一個常見的誤解) –

+0

@HarryJohnston庫實現不受ISO C++規則的約束,甚至可能不會用C++ –

回答

2

C的黎明之間(追溯到至少到1974)和1989年,如果兩個結構共享一個公共初始序列,語言明確地允許代碼使用一種結構類型的指針來檢查的CIS成員另一個。在C99標準中,該權限僅限於兩種結構類型均爲聯合類型的一部分的情況,該聯合類型的完整聲明在檢查CIS值時可見;有些人堅持認爲,因爲1989年的作者意在施加這樣的限制,它也適用於C89。另外,一些編譯器編寫者堅持認爲,因爲標準的作者只是爲了保證適用於通過聯合類型的左值進行的訪問,他們會忽略標準的一部分,該部分表示「完整聯合的定義」類型「必須可見。

實現允許提供超出標準要求的保證。因爲在C99之前編寫代碼的非精神科人員沒有理由期望他們需要包含其他不必要的工會聲明以利用獨聯體擔保,並且因爲從該時代編寫的許多代碼依賴於這些擔保,儘管缺少這樣的聲明,任何想要編寫實現適用於這樣的代碼必須支持它們無論標準是否需要這種支持。雖然沒有特別好的理由說明爲什麼頭文件的更新不應該包含聯合類型聲明,但我不確定有多少編譯器會關心它的存在與否。我見過的編譯器要麼支持CIS保證,即使沒有一個完整的聯合類型聲明是可見的,或者即使在聲明存在的時候,也要拒絕CIS保證(忽略標準)。

相關問題