C 来自不兼容指针类型的赋值:强制类型?

C 来自不兼容指针类型的赋值:强制类型?,c,pointers,assignment-operator,C,Pointers,Assignment Operator,此时,bb和aa已初始化,bb包含有效值 struct b { uint8_t b; ... }; struct b *bb; 但是,这会导致编译器警告,这是有意义的: 警告:来自不兼容指针类型[-Wincompatible指针类型]的分配 这样做安全吗 aa->a = &bb->b; aa->a = (uint32_t *)&bb->b; 这样做安全吗 aa->a = &bb->b; aa->a = (uin

此时,
bb
aa
已初始化,
bb
包含有效值

struct b {
   uint8_t b;
   ...
};
struct b *bb;
但是,这会导致编译器警告,这是有意义的:

警告:来自不兼容指针类型[-Wincompatible指针类型]的分配

这样做安全吗

aa->a = &bb->b;
aa->a = (uint32_t *)&bb->b;
这样做安全吗

aa->a = &bb->b;
aa->a = (uint32_t *)&bb->b;
C允许您在不同的对象指针类型之间进行转换。将表达式
&bb->b
的值转换为
aa->a
类型后,您当然可以将结果分配给
aa->a
。从这个意义上说,这一声明本身是安全的

但事后取消引用
aa->a
是不安全的。这样做的结果是显式未定义的。因为我推断这是你下一步打算做的,不,你的总体计划是不安全的


如果您想要一个可以指向
uint32\u t
uint8\u t
的指针,请使用
void*
char*
无符号char*
。如果
uint8\u t
很可能是
unsigned char
的别名,您也可以使用
uint8\u t*

通常为什么要尝试将
uint8\u t*
分配给
uint32\u*
?否,因此出现类型错误。为什么要这样做?我正在编写一个应用程序,它打开一个
netlink
套接字,并与Linux内核子系统一起工作。现在,数据可能作为netlink头之后的头的一部分出现(该头是UAPI,其中对象是
u8
),或者数据可能作为32位长的TLV属性出现,因此我的结构中有
uint32类型的
uint32
。为什么不使用
union
void*
?另外,也许我有误解,但这并不能真正解释为什么您强制分配指针而不是整数值本身。@jamesdlin,我正在使用的应用程序没有为那些
my_struct
成员分配内存,而是将指针分配给
netlink
缓冲区内存,从
recv()
。这只是一个我必须处理的设计。我不同意这里对转换安全的乐观看法。“C允许您在不同的对象指针类型之间进行转换”Hmmm:“如果生成的指针没有正确地与引用的类型对齐,则行为是未定义的。”
bb->b
对于
(uint32_t*)&bb->b
不一定对齐,并且该代码存在UB风险,无论以后是否取消引用。OTOH,也许
struct
都有相同的对齐方式?这是一个很好的观察结果,@chux。实际上是两个。当然,所有结构指针类型都具有相同的表示形式。如果我们吹毛求疵,那么我认为这实际上并不要求它们具有相同的对齐要求,但在实践中,我认为在将指向一个结构的第一个成员的指针转换为另一个结构的第一个成员的类型时,不存在对齐问题的合理可能性。