2016-08-19 62 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