【问题标题】:Is storing a byte in a void pointer cross-platform safe?将字节存储在 void 指针跨平台安全吗?
【发布时间】:2021-09-13 01:16:16
【问题描述】:
void *vp = (void *)5;
uint8_t i = (uint8_t)vp;

i == 5 在所有 8 位和更高的 CPU 上都可以吗?这样做有什么风险?有没有更好的方法让变量存储 8 位整数文字或 C99 中的指针?

我有一个函数指针数组,指向带有 void * 的函数。有些函数需要将 void * 解释为 uint8_t。

【问题讨论】:

  • 你为什么要这样做?
  • 正确的做法是使用包含void *uint8_t 的联合。这就是工会的用途。
  • 如果要存储为整数类型,请使用uintptr_t
  • warning: initialization of ‘void *’ from ‘int’ makes pointer from integer without a cast GCC 这么说,这并没有明确启用任何警告。同样根据@dbush 评论,您能否扩展您的问题,因为尚不清楚您要做什么或为什么。
  • @marko 是的,如果回调都将指针作为参数并使用指针作为指针,那很好。我还没有看到参数是指针或其他任意类型的回调。这不是一个标准的习语,它通常被称为意大利面条代码。

标签: c language-lawyer platform-agnostic


【解决方案1】:

void *vp = 5; 不应该编译; C 标准至少要求编译器发出诊断消息。您可以使用void *vp = (void *) 5; 请求转换,也可以使用(uint8_t) vp 请求反向转换。 C 标准不保证这将再现原始值。 (涉及指针的转换在 C 2018 6.3.2.3 中指定。)它可能适用于大多数 C 实现。

由 C 标准定义的替代方法是使用偏移量到您已经拥有的一些足够大的对象中。例如,如果你有一些数组A,并且你想在void * 中存储一些小的数字n,那么你可以这样做:

void *vp = (char *) A + n; // Point n bytes into the object A.

您可以通过以下方式恢复号码:

(char *) vp - (char *) A // Subtract base address to recover offset.

【讨论】:

  • 更新问题
  • 我怀疑“适用于大多数实现”的条件是 CPU 能够在通用寄存器中存储整数类型和地址,而无需通过内存进行转换 - 在哪种情况下的字节序可能会咬你。您可能必须努力找到一个不起作用的地方。
【解决方案2】:

C 标准确实允许整数和指针之间的转换,但是它并没有准确解释它应该如何发生。这取决于每个具体的实现。

C standard 的第 6.3.2.3 p5-6 节描述了这些转换:

5 整数可以转换为任何指针类型。除非前面指定,结果是实现定义的, 可能未正确对齐,可能未指向实体 被引用的类型,并且可能是一个陷阱表示。

6 任何指针类型都可以转换为整数类型。除非前面指定,结果是实现定义的。如果 结果不能用整数类型表示,行为 未定义。结果不必在值范围内 任何整数类型。

特别是在 gcc 下,您正在执行的操作将有效,但不能保证在所有编译器或架构上都有效。

保证可以工作的是获取复合文字的地址:

void *vp = &(uint8_t){5};
uint8_t i = *(uint8_t *)vp;

这会创建一个uint8_t 类型的临时对象并获取其地址。然后可以根据 6.3.2.3 的第 1 段将该地址转换为完全符合标准的 void * 并返回:

指向void 的指针可以转换为或从指向任何对象类型的指针转​​换。 指向任何对象类型的指针都可以转换为指向void 的指针,然后再转换回来;结果应与原始指针比较。

复合文字的生命周期是定义它的块的生命周期。因此,只要在该块结束后不使用指针,它就会起作用。

但是,如果您打算将它传递给启动线程的函数,则最好为该值动态分配内存并传递它。否则,您将面临定义复合文字的函数在线程函数运行时返回的风险,这可能会尝试使用该指针。

【讨论】:

  • 特别是在 gcc 下,你正在做的事情会起作用除了 GCC 文档说它是 UB。
  • @LanguageLawyer 不是。见this page
猜你喜欢
  • 2015-01-01
  • 1970-01-01
  • 2018-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-24
  • 2018-08-27
相关资源
最近更新 更多