c - 是否将指针转换到 intptr_t,对其进行算术运算,然后转换回已定义的行为?

标签 c gcc c11

假设我想将一个 void* 指针移动 4 个字节。是以下等价物:

答:

void* new_address(void* in_ptr) {
    intptr_t tmp = (intptr_t)in_ptr;
    intptr_t new_address = tmp + 4;
    return (void*)new_address;
}

乙:

void* new_address(void* in_ptr) {
    char* tmp = (char*)in_ptr;
    char* new_address = tmp + 4;
    return (void*)new_address;
}

都是定义的行为吗?是一种更受欢迎/接受的惯例吗?还有其他理由使用一个而不是另一个吗?
我们只考虑 64 位系统。如果 intptr_t 不可用,我们可以改用 int64_t。

上下文是一个自定义内存分配器,它需要在将新内存块分配到特定地址之前移动指针(出于对齐目的)。我们还不知道结果指针将指向什么对象,但我们知道我们需要将它移动到特定位置,在上面的示例中是 4 个字节。

最佳答案

Michael Kerrisk在第 1415 页上说,

The C standards make one exception to the rule that pointers of different types need not have the same representation: pointers of the types char * and void * are required to have the same internal representation.

所有 C 标准保证 (7.18.1.4) 是您可以将 void* 值转换为 intptr_t(或 uintptr_t)并返回再次并以指针的相等值结束。

这里的细微差别是,如果正在使用 void*,我们将无法应用数学运算(包括 ==)。

关于c - 是否将指针转换到 intptr_t,对其进行算术运算,然后转换回已定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64861886/

相关文章:

c - 非阻塞套接字(tcp)缓冲区消息逐一处理

为 Mips 架构编译 C

c - 必须在多大程度上使用原子类型来保证跨线程可见性?

linux - 用于了解可执行文件的文本、BSS 等字段的命令

c++ - 在 gcc 和 Visual C++ 中使用 '>>'

c - 带有 gcc 和无符号整数的 SIGFPE

c - 为什么示例 A 编译而示例 B 出现 "initializer element is not constant"错误

c - 声明一个返回数组的函数指针

c - 代码中可能存在内存错误以及可能的解决方案?

c - C语言100位变量的值