我想计算两个地址之间的字节数。
uint32_t length = &b - &a;
当a和b为uint32_t时,长度为1。
uint32_t a, b;
uint32_t length = &b - &a; // length is one
当a和b为uint8_t时,长度为4。
uint8_t a, b;
uint32_t length = &b - &a; // length is four
因此,计算是a和b之间的uint32_t或uint8_t的数量,而不是我错误预期的地址之间的数学差异。
我的问题:C语言的哪一部分包括地址计算?有人可以引用讨论该主题的规范中的位置吗?
答案 0 :(得分:3)
指针减法在C standard:
的第6.5.6节中介绍3 对于减法,以下之一应保留:
- 两个操作数都有算术类型;
- 两个操作数都指向兼容的完整对象类型的限定或非限定版本; 或
- 左操作数是指向完整对象类型的指针,右操作数是整数类型。
...
9 当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组最后一个元素的元素 宾语;结果是两者下标的差异 数组元素。结果的大小是实现定义的,和 它的类型(有符号整数类型)是在ptrdiff_t中定义的 头。如果结果在对象中无法表示 该类型,行为未定义。换句话说,如果 表达式P和Q分别指向第i和第j个元素 对于数组对象,表达式(P) - (Q)具有提供的值i-j 该值适合ptrdiff_t类型的对象。而且,如果 表达式P指向数组对象的元素或一个元素 超过数组对象的最后一个元素,表达式Q指向 到同一个数组对象的最后一个元素,表达式 ((Q)+1) - (P)具有与((Q) - (P))+ 1相同的值和 - ((P) - ((Q)+1)), 如果表达式P指向过去的一个,则其值为零 数组对象的元素,即使表达式(Q)+1没有 指向数组对象的元素。
所以区别在于两者之间的元素的数量,而不是字节数。
请注意,这只允许减去同一数组的两个元素之间的指针。所以这是合法的:
uint32_t a[5];
uint32_t len = &a[1] - &a[0];
但这不是:
uint32_t a, b
uint32_t len = &b - &a;
答案 1 :(得分:1)
。否则就是UB
但是如果变量位于相同的连续地址空间中 - 例如在ARM中,如果指针具有相同的类型或者将它们转换为相同的类型,则将定义此算法的结果。
这不是符合C标准的代码
#include <stdio.h>
#include <stdint.h>
uint64_t c;
uint64_t d;
uint16_t e;
uint8_t f;
int main(void)
{ uint32_t a,b;
printf("%lld\n", (long long)((uint8_t *)&b - (uint8_t *)&a));
printf("%lld\n", (long long)((uint8_t *)&c - (uint8_t *)&a));
printf("%lld\n", (long long)((uint8_t *)&d - (uint8_t *)&c));
printf("%lld\n", (long long)((uint8_t *)&e - (uint8_t *)&d));
printf("%lld\n", (long long)((uint8_t *)&f - (uint8_t *)&c));
}
将打印的内容是100%直至实施。一些结果可能有另一种意义。
这种算法在嵌入式开发中使用,例如通过在链接器脚本中定义符号(例如bss的开始和bss的结尾),然后这些符号(实际上是它们的地址)用于执行诸如归零之类的操作bss或初始化数据段
你可以在Linux机器上试试: https://ideone.com/dm0R5M
答案 2 :(得分:0)
我想计算两个地址之间的字节数。
如果地址在同一个数组中,代码可以减去指针以获得差异中元素数量的计数。然后乘以类型的大小来报告“字节”的数量。
ptrdiff_t diff = &a[some_index] - &a[some__other_index];
diff *= sizeof a[0];
printf("Diff %td\n", diff);
如果不知道2个对象的地址在同一个数组中,代码可以仔细减去,但根据内存模型,差异可能代表也可能不代表“字节”差异。 IAC,下面避免了未定义的行为。
#include <inttypes.h>
#include <stdio.h>
void *va = &a;
void *vb = &b;
// optional types
uintptr_t ua = (uintptr_t)va;
uintptr_t ub = (uintptr_t)vb;
uintptr_t diff = ua > ub ? ua - ub : ub - ua;
printf("Maybe byte difference of %" PRIuPTR "\n", diff);