2016-08-19 58 views
0

下面是一個符合標準的C程序(以及哪個標準)?如果它不符合(通過違反嚴格的別名規則或其他方式)對於GCC或任何其他常用的C編譯器是否是「安全的」?集合C結構與其成員之間的指針是否符合標準?

int main() 
{ 
    typedef struct { 
     int data; 
    } Type1; 

    typedef struct { 
     float data; 
    } Type2; 

    typedef struct { 
     Type1 type1; 
     Type2 type2; 
    } Aggregate; 

    Aggregate aggregate; 
    aggregate.type1.data = 1; 
    aggregate.type2.data = 2.0; 

    Aggregate *p_aggegregate = &aggregate; 
    Type1  *p_type1  = (Type1*) &aggregate; 
    Type2  *p_type2  = (Type2*) &aggregate; 

    int data1 = p_type1->data; 
    float data2 = p_type2->data; 

    return 0; 
} 
+1

'p_type2'不指向類型爲Type2的對象,您如何建議使用該指針?或者你不打算使用它? – 2501

+0

僅僅指向一個對象的指針不能訪問它。所以別名不是一個問題。 – 2501

+0

'Type1 * p_type1 =&aggregate'和'Type2'變體是不兼容的指針轉換。 – ensc

回答

-1

嚴格來說,你的程序是符合標準(C11,C99,不知道有關ķ& R)。它僅包含指針轉換,並有C標準中很少的規則,是制約其

Type1  *p_type1  = &aggregate; 
Type2  *p_type2  = &aggregate; 

符類型安全,可能每一個編譯器將發出警告它作爲一個無效的類型轉換。 但它是由

7所述的指針的對象類型所覆蓋可被轉換成一個指針到一個不同的對象類型。 [6.3.2.3「指針」,C11草案]

我還沒有找到其需要顯式轉換

規則
Type1  *p_type1  = (Type1 *)&aggregate; 

和上述段落採用了類似的措辭像第1段一個這允許通常使用隱含的東西來/從void *轉換。

訪問這兩個變量是有效的,因爲&aggregate == &aggregate.type1

但如前所述,以這種方式寫東西是一種非常糟糕和不安全的風格,而通常的編碼風格會將其視爲錯誤。如果您添加例如在type1之前的char foo;屬性。

編輯:

程序無效;它違反

- 左操作數具有原子,合格,不合格或指針類型,並[...]兩個操作數都指向兼容的類型的合格或不合格的版本[...] [6.5.16.1 「簡單賦值」]

2要使兩種指針類型兼容,既應相同合格兩者應指針兼容的類型。 [6.7.6.1「指針說明符」]

+0

謝謝;修正了paragrah。但是對齊可以改變。 C標準沒有定義結構如何對齊。可能存在體系結構相關的ABI,它們要求結構像最一致的屬性一樣對齊。但這不是C所要求的。 – ensc

+0

10一些ABI需要這個,但不是C. – ensc

+0

如果指針沒有指向兼容類型,則需要顯式強制轉換以強制轉換。這是簡單賦值6.5.16.1的規則所要求的。限定符也必須匹配。相關部分「左操作數具有原子性,合格性或非限定性指針類型,並且(考慮 左值操作數在左值轉換後將具有的類型),兩個操作數都是 指向合格或非合格版本的兼容類型的指針, 到左邊有右側指向的所有類型的限定符;「 – Lundin