【问题标题】:Cast void pointer to “type” variable or use memcpy?将 void 指针转换为“类型”变量或使用 memcpy?
【发布时间】:2021-10-24 02:14:39
【问题描述】:

我无法找到答案。我在 C 中使用哪种方法有关系吗?

int get_int(void *vptr) {
    return *(int *)vptr;
}

int get_int(void *vptr) {
    int i = 0;
    memcpy(&i, vptr, sizeof(int));
    return i;
}

在我的测试中似乎给出了相同的结果,但在每种情况下都是等效的吗?

【问题讨论】:

  • 你能展示你的测试用例吗?
  • 这取决于指针指向的位置。如果它指向你知道是对齐的int 类型的变量,那么前一个版本是正确的并且可能更有效。如果不知道指针指向的位置,则不能使用以前的版本。

标签: c embedded


【解决方案1】:

主要区别在于 memcpy 将在更多情况下工作——它只要求从中复制的内存包含适当类型的数据。 cast-and-dereference 要求并且还要求指针对于访问该类型是有效的。在大多数机器上,这(只是)需要正确对齐。强制转换还允许编译器假定它不会使用不同类型的值进行别名。

最终结果是 memcpy 可能“更安全”,但也可能更昂贵。

【讨论】:

  • 我现在明白了。非常感谢,感谢您的帮助。
【解决方案2】:

但这在每种情况下都等效吗?

没有。

*(int *)vptr 依赖于 int 对齐。如果vptr 不指向int 分配的数据,则结果为UB。

memcpy() 没有要求。只要数据不是陷阱(罕见),它就“有效”。

【讨论】:

  • 所以只要我确定数据是 int,两者都做同样的事情?
  • @Alejandro 问题是 1) 如果vptr 可以转换为正确的int*(如果它不满足最低int 对齐要求则不能 - 示例int * 可能只工作在偶数边界上,但vptr 是奇数)和 2)如果 data 不是正确编码的int(今天第二期非常罕见)。使用memcpy(),即使vptr 指针是奇数,数据副本也能正常工作。
  • 完美,非常感谢。
【解决方案3】:

,它不等同,因为不管你信不信,并非所有指针在所有情况下都是相同的(尽管在 x86+ 架构上它们是相同的)。

但是,演员表将在定义的地方起作用。

【讨论】:

    猜你喜欢
    • 2021-09-20
    • 1970-01-01
    • 2017-10-07
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多