據我所知,GCC支持C++中的所有C99功能。但是C99嚴格別名是如何在C++代碼中處理的?C99嚴格的混淆規則(GCC)
我知道用C鑄造不相關的類型不是嚴格的別名安全的,可能會產生不正確的代碼,但是C++呢?由於嚴格的別名不是C++標準的一部分(這是否正確?),GCC必須自己指定語義。
我圖const_cast
和static_cast
在相關類型之間轉換,因此它們是安全的,而reinterpret_cast
可以打破嚴格的別名規則。
這是一個正確的理解?
據我所知,GCC支持C++中的所有C99功能。但是C99嚴格別名是如何在C++代碼中處理的?C99嚴格的混淆規則(GCC)
我知道用C鑄造不相關的類型不是嚴格的別名安全的,可能會產生不正確的代碼,但是C++呢?由於嚴格的別名不是C++標準的一部分(這是否正確?),GCC必須自己指定語義。
我圖const_cast
和static_cast
在相關類型之間轉換,因此它們是安全的,而reinterpret_cast
可以打破嚴格的別名規則。
這是一個正確的理解?
不,你可能混合了不同的東西。
嚴格的鋸齒規則與C99標準沒有任何關係。自[標準化]時代開始以來,嚴格的鋸齒規則植根於C和C++中存在的部分標準。在C89/90(6.3)以及C++ 98(3.10/15)中存在禁止通過另一種類型的左值訪問一種類型對象的子句。這就是嚴格的別名是什麼,不多也不少。並非所有編譯器都希望(或敢於)執行或依賴它。 C和C++語言有時被用作「高級彙編」語言,嚴格的別名規則常常會干擾這些用途。 GCC做出了這個大膽的舉動,並決定開始依靠優化中的嚴格別名規則,經常從這些「集合」類型中引起投訴。
確實,在C++中打破嚴格別名規則的最簡單的方法是reinterpret_cast
(當然還有C風格強制轉換)。然而,static_cast
也可以用於該目的,因爲它允許一個通過使用void *
如在「鏈接」的中間類型打破嚴格別名投
int *pi;
...
double *pd = static_cast<double *>(static_cast<void *>(pi));
const_cast
在一個兼容的編譯器不能打破嚴格混疊。
至於C99 ...... C99所做的是restrict
限定詞。這與鋸齒有直接關係,但它本身並不是所謂的嚴格鋸齒。
static_cast
也可以破壞別名規則,因爲編譯器相信您會確保目標類型與對象的實際運行時類型相關。考慮:
extern void f(double*, int*); // compiler may optimize assuming that arguments don't overlap
double d;
void* pv = &d;
int* pi = static_cast<int*>(pv);
f(&d, pi); // assumption is violated
這個概念在Cpp中是一樣的;因爲您可以使用C風格演員指導您完成對嚴格別名的安全考慮。
簡而言之:不,使用Cpp鑄造的方法(您所概述的)不能安全地涵蓋所有情況。破壞規則的一種常見方式是使用static_cast投射指針。
只要調出編譯器警告 - 它會(或者,應該)告訴你什麼是不安全的。
你說得對,我在想C99'restrict'關鍵字,而不是嚴格的別名。出於某種原因,它在我的腦海中以這種方式根深蒂固(「C99」+「嚴格別名」)。 – 2010-05-05 07:04:42
那麼究竟是什麼問題?這是否意味着任何違反嚴格別名規則的C89/C99/C++ 98代碼在技術上都是不正確的(禁止像-fno-strict-aliasing這樣的特定於編譯器的開關)? – 2010-05-05 07:07:46
@Checkers:我將數字添加到我的答案中。是的,打破嚴格別名規則的代碼在C89和C++ 98中展現出未定義的行爲。 – AnT 2010-05-05 07:16:54