C 如何计算两个地址之间的距离?
我想计算两个地址之间的字节数C 如何计算两个地址之间的距离?,c,pointers,memory,byte,sizeof,C,Pointers,Memory,Byte,Sizeof,我想计算两个地址之间的字节数 uint32_t length = &b - &a; 当a和b为uint32时,长度为1 uint32_t a, b; uint32_t length = &b - &a; // length is one 当a和b为uint8时,长度为4 uint8_t a, b; uint32_t length = &b - &a; // length is four 因此,计算是a和b之间的uint32_t或uint
uint32_t length = &b - &a;
当a和b为uint32时,长度为1
uint32_t a, b;
uint32_t length = &b - &a; // length is one
当a和b为uint8时,长度为4
uint8_t a, b;
uint32_t length = &b - &a; // length is four
因此,计算是a和b之间的uint32_t或uint8_t的数量,而不是我错误地预期的地址之间的数学差
我的问题是:C语言的哪一部分包括地址的计算?是否有人可以引用规范中讨论该主题的位置?指针减法在本手册第6.5.6节中介绍: 3对于减法,以下其中一项应适用:
- 两个操作数都具有算术类型李>
- 两个操作数都是指向兼容完整对象类型的合格或不合格版本的指针或
- 左操作数是指向完整对象类型的指针,右操作数是整数类型
ptrdiff_t diff = &a[some_index] - &a[some__other_index];
diff *= sizeof a[0];
printf("Diff %td\n", diff);
请注意,这只允许在同一数组的两个元素之间减去指针。所以这是合法的:
uint32_t a[5];
uint32_t len = &a[1] - &a[0];
但这不是:
uint32_t a, b
uint32_t len = &b - &a;
第6.5.6节介绍了指针减法: 3对于减法,以下其中一项应适用:
- 两个操作数都具有算术类型李>
- 两个操作数都是指向兼容完整对象类型的合格或不合格版本的指针或
- 左操作数是指向完整对象类型的指针,右操作数是整数类型
ptrdiff_t diff = &a[some_index] - &a[some__other_index];
diff *= sizeof a[0];
printf("Diff %td\n", diff);
请注意,这只允许在同一数组的两个元素之间减去指针。所以这是合法的:
uint32_t a[5];
uint32_t len = &a[1] - &a[0];
但这不是:
uint32_t a, b
uint32_t len = &b - &a;
在符合标准的C中,如果指针具有不同的类型或未指向同一内存块(即表或以其他方式分配),则不允许使用指针算术。否则就是UB 但是,如果变量位于相同的连续地址空间中——例如,在ARM uC中,如果指针具有相同的类型,或者您将它们转换为相同的类型,则将定义此算法的结果 这不是符合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));
}
#包括
#包括
uint64_t c;
uint64_t d;
uint16_t e;
uint8_t f;
内部主(空)
{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归零或初始化数据段等操作
您可以在Linux机器上尝试:
如果指针具有不同类型或未指向同一内存块(即表或以其他方式分配),则不允许在标准兼容C中使用指针算术。否则就是UB 但是,如果变量位于相同的连续地址空间中——例如在ARM uC中,如果指针具有相同的类型,或者您将它们强制转换为相同的类型,则将定义此算法的结果