【问题标题】:Is This "Type Punning" Well-Defined?这种“类型双关语”定义明确吗?
【发布时间】:2013-08-26 00:17:36
【问题描述】:

我想知道,是否在指向不完整类型未定义行为的指针之间进行强制转换?

struct _obj;
typedef _obj obj;

typedef struct{
    int val;
} obj_int;

void print_stuff(obj* o){
    printf("%d\n", ((*obj_int)(o)) -> val);
}

【问题讨论】:

  • obj* o 是从哪里来的?另一个演员表,或者struct _obj 已完成并且struct _obj 的实际实例存在并且o 是它的地址?

标签: c


【解决方案1】:

通常。

标准 6.3.2.3/7:

指向对象或不完整类型的指针可以转换为指向不同类型的指针 对象或不完整类型。如果生成的指针未正确对齐 指向类型,行为未定义。否则,当再次转换回来时, 结果应与原始指针比较。当指向对象的指针是 转换为指向字符类型的指针,结果指向的最低寻址字节 物体。结果的连续递增,直到对象的大小,产生指针 到对象的剩余字节。

因此,如果o 指向第一个成员是int 的任何结构对象,那么您就可以了。如果它指向从malloc 获得的内存的开头,其中已经写入了int 的表示,那么你很好。但如果它指向 char[sizeof(int)] 或类似的东西,您可能会遇到对齐问题。

【讨论】:

  • 我同意“如果o 指向第一个成员是int 的任何结构对象,那么你很好”。目前尚不清楚“int 的表示已被写入”,这听起来不像是正确的条件(即 intchar 类型的左值用于存储该值) .
  • 这是哪个版本的标准?我的副本中的 6.3.2.3/7 中没有出现“不完整类型”的字样。
  • @Paul:6.3.2.3,不是 6.2.3.2
  • 在C11中,不完整的对象类型仍然属于对象类型的范畴,见6.2.5/1。
  • @BenVoigt:是的,这是一个错字,我将其更正为 6.3.2.3。同意 6.2.5/1,只是好奇我的标准是否过时。
【解决方案2】:

您没有提供足够的信息来回答您的问题。 如果您将obj_int* 转换为obj*,然后将其传递给print_stuff那么根据 C 标准,您的代码是合法的,因为您可以将指针转换为另一个指针类型并返回。但是,如果 print_stuff 的参数是通过任何其他方式获得的,那么您就有未定义的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 2011-06-10
    • 2011-10-19
    • 2011-08-26
    • 2016-11-30
    • 1970-01-01
    相关资源
    最近更新 更多