从不兼容的指针类型分配:强制类型?

assignment from incompatible pointer type: forcing the type?

提问人:Mark 提问时间:1/11/2019 更新时间:1/11/2019 访问量:1396

问:

struct my_struct {
   int p;
   uint32_t *a;
   ...
};
struct my_struct *aa;

...

struct b {
   uint8_t b;
   ...
};
struct b *bb;

此时,已初始化,包含有效值。bbaabb

aa->a = &bb->b;

但是,这会导致编译器警告,这是有道理的:

warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]

执行以下操作是否安全?

aa->a = (uint32_t *)&bb->b;
C 指针 赋值运算符

评论

4赞 jamesdlin 1/11/2019
为什么要尝试将 a 分配给 ?uint8_t*uint32_t*
3赞 melpomene 1/11/2019
通常?否,因此类型错误。你为什么要这样做?
0赞 Mark 1/11/2019
我正在编写一个应用程序,该应用程序可以打开套接字并与 Linux 内核子系统一起使用。现在,数据可能作为 netlink 标头后面的标头的一部分(该标头是 UAPI,其中 object 是),或者数据可能作为 32 位长的 TLV 属性出现,因此我的类型为 my_struct。netlinku8auint32_t
1赞 jamesdlin 1/11/2019
为什么不使用 a or then?另外,也许我误解了,但它并没有真正解释为什么你要强行分配指针而不是整数值本身。unionvoid*
0赞 Mark 1/11/2019
@jamesdlin,我正在使用的应用程序不会为这些成员分配内存,而是将指针分配给缓冲内存,从 .这只是我必须处理的设计。my_structnetlinkrecv()

答:

2赞 John Bollinger 1/11/2019 #1

执行以下操作是否安全?

aa->a = (uint32_t *)&bb->b;

C 允许您在不同的对象指针类型之间进行转换。将表达式的值转换为 类型后,您当然可以将结果分配给 。从这个意义上说,这种说法本身是安全的。&bb->baa->aaa->a

但事后取消引用是不安全的。这样做的结果是明确未定义的。据我推断,这就是你接下来打算做的事情,不,你的整体计划是不安全的。aa->a

如果需要一个可以指向 a 或 a 的指针,请使用 或 a 或 。在极有可能是 的别名的情况下,您还可以使用 .uint32_tuint8_tvoid *char *unsigned char *uint8_tunsigned charuint8_t *

评论

2赞 chux - Reinstate Monica 1/11/2019
不同意这里对转换安全性的乐观看法。“C 允许您在不同的对象指针类型之间进行转换” Hmmm: “如果生成的指针未正确对齐引用的类型,则行为未定义。” 肯定不对齐,并且此代码有 UB 风险 - 无论是否在以后取消引用。OTOH,也许都有相同的对齐方式?bb->b(uint32_t *)&bb->bstruct
2赞 John Bollinger 1/11/2019
@chux,这是一个很好的观察。实际上,有两个。当然,所有结构指针类型都具有相同的表示形式。如果我们吹毛求疵,那么我认为这实际上并不要求它们具有相同的对齐要求,但在实践中,我认为在将指向一个结构的第一个成员的指针转换为另一个结构的第一个成员的类型时,不存在任何合理的可能性。