【问题标题】:assignment from incompatible pointer type: forcing the type?来自不兼容指针类型的赋值:强制类型?
【发布时间】:2019-06-05 20:27:08
【问题描述】:
struct my_struct {
   int p;
   uint32_t *a;
   ...
};
struct my_struct *aa;

...

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

此时bbaa已经初始化,bb包含有效值。

aa->a = &bb->b;

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

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

执行以下操作是否安全?

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

【问题讨论】:

  • 您为什么要尝试将uint8_t* 分配给uint32_t*
  • 一般?不,因此类型错误。你为什么要这样做?
  • 我正在编写一个应用程序,它打开一个netlink 套接字并与 Linux 内核子系统一起工作。现在,数据可能作为 netlink 标头之后的标头的一部分(并且该标头是 UAPI,其中对象是 u8),或者数据可能以 32 位长 TLV 属性的形式出现,因此我有 a在 my_struct 中属于 uint32_t 类型。
  • 那为什么不使用unionvoid* 呢?另外,也许我误解了,但这并不能真正解释为什么您要强制分配 指针 而不是整数值本身。
  • @jamesdlin,我正在使用的应用程序不会为那些my_struct 成员分配内存,而是分配指向netlink 缓冲内存的指针,从recv() 获得。这只是我必须处理的设计。

标签: c pointers assignment-operator


【解决方案1】:

执行以下操作是否安全?

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

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

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

如果您想要一个可以指向uint32_tuint8_t 的指针,请使用void *char *unsigned char *。如果uint8_t 很可能是unsigned char 的别名,您也可以使用uint8_t *

【讨论】:

  • 不同意这里对转换安全的乐观看法。 “C 允许您在不同的对象指针类型之间进行转换” 嗯:“如果结果指针未正确对齐引用的类型,则行为未定义。” bb->b 不一定与 (uint32_t *)&bb->b 对齐,并且此代码存在 UB 风险 - 有或没有稍后取消引用。 OTOH,也许struct 都共享相同的对齐方式?
  • 这是一个很好的观察,@chux。两个,其实。当然,所有结构指针类型都有相同的表示。如果我们在吹毛求疵,那么我认为这实际上并不要求它们具有相同的对齐要求,但在实践中,我认为在将指针转换为 one 的第一个成员时不存在任何合理的对齐问题的可能性结构到另一个结构的第一个成员的类型。
猜你喜欢
  • 2019-08-09
  • 2014-12-14
  • 2014-07-27
  • 1970-01-01
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
相关资源
最近更新 更多