Preface:我知道这方面的用例很难找到.这个问题纯粹是理论上的,是由好奇心引起的.

采取以下措施:

char b[SOME_SIZE];

是这样的吗:

((char *)5) + ((uintptr_t)b)

保证产生与更传统的相同的结果:

(b) + ((uintptr_t)5)

如果实现定义了uintptr_t

如果我把一个'pointer'(包含一个偏移量)加到一个包含一个地址的uintptr_t上,结果会和预期的一样吗?即,就像我直接把偏移量加到地址上一样?

推荐答案

严格地说,这是一种未定义的行为.

只有当指针指向有效数组对象(或单个对象)的成员,并且结果指向同一数组对象的成员时,执行指针算术,特别是将值添加到指针才有效.这在关于加法运算符的C standard条的第6.5.6p8节中有详细说明:

将整型表达式相加或相减时 在指针中,结果具有指针操作数的类型.如果 指针操作数指向数组对象的元素,数组 足够大,则结果指向从 元素的下标之间的差异 结果数组元素和原始数组元素等于整数表达式. 换句话说,如果表达式P指向 数组对象,表达式(P)+N(相当于N+(P))和(P)-N (其中N的值为n)分别指向第i+n次和 I−数组对象的第n个元素,如果它们存在的话.此外,如果 表达式P指向数组对象的最后一个元素 表达式(P)+1指向数组对象的最后一个元素之后一个, 如果表达式Q指向数组的最后一个元素 对象,则表达式(Q)-1指向数组的最后一个元素 对象.如果结果指向最后一个元素之后的一个元素,则为If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. 不能用作一元*的操作数. 被计算的运算符.

在这个表达式中:

((char *)5) + ((uintptr_t)b)

指针表达式(char *)5没有指向有效的对象(除非您所在的系统明确允许使用"5"作为有效地址),因此对其执行算术运算是未定义的.

在地址只是一个32位或64位值的系统上,这将是probably,但不能保证这一点.一些编译器有pointer provenance的概念,它跟踪指针指向的对象,这样的构造可能会与执行优化时使用此概念的编译器冲突.

我见过一对指针ab的例子,其中(uintptr_t)a == (uintptr_t)b为真,而a == b为假.

C++相关问答推荐

漏洞仅出现在FreeBSD上,但在Windows、Linux和MacOS上运行得非常好

Bison解析器转移/减少冲突

segfault在C中使用getline()函数

你能用自己的地址声明一个C指针吗?

在C中使用强制转换将uint16_t转换为uint8_t [2]是否有效?

如何在C宏中确定Windows主目录?

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

我可以在C中声明不同长度数组的数组而不带变量名吗?

将常量转换为指针会增加.数据大小增加1000字节

在C23中使用_GENERIC实现带有右值的IS_POINTER(P)?

用C++从外部ELF符号读取值

如何在C中使数组变量的值为常量?

处理来自浏览器的HTTP请求

安全倒计时循环

不确定如何处理此编译错误

在运行时判断C/C++指针是否指向只读内存(在Linux操作系统中)

为什么二进制文件的大小不会随着静态数据的大小而增加?

如果类型是新的,offsetof是否与typeof一起工作?

与 C 相比,C++ 中无副作用的无限循环的好处是 UB?

用于内存布局的size命令(文本、数据、bss)