类似指针的区别

相同类型的两个指针的差异总是一个。

#include #include int main(){ int a = 5,b = 10,c; int *p = &a,*q = &b; c = p - q; printf("%d" , c); return 0; } Output is 1. 

我不明白这背后的原因

行为未定义。

C99 6.5.6第9段说:

当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异。

同一节中的第7段说:

出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型作为其元素类型。

第4节第2段说:

如果违反了出现在约束之外的“应该”或“不应该”的要求,则行为是不确定的。 未定义的行为在本国际标准中以“未定义的行为”或省略任何明确的行为定义的方式另有说明。 这三者之间的重点没有区别; 他们都描述了“未定义的行为”。

3.4.3将术语“未定义行为”定义为:

行为,使用不可移植或错误的程序结构或错误数据,本国际协会没有要求

注意可能的未定义行为范围从完全忽略不完全结果的情况,到翻译或程序执行期间的行为,以文档特有的环境(有或没有发出诊断消息),终止翻译或执行(使用发出诊断信息)。

鉴于声明:

 int a = 5, b = 10, c; 

评估&b - &a可能会产生看似合理的结果,例如1-1 。 (合理的结果始终是未定义行为的可能症状;它是未定义的,不需要崩溃。)但编译器没有义务将ab放在内存中相对于彼此的任何特定位置,即使它这样做,减法不保证有意义。 优化编译器可以自由地转换您的程序, 假设其行为已被很好地定义,从而导致代码在违反该假设时可以以任意不好的方式运行。

通过编写&b - &a ,您实际上向编译器承诺这是一个有意义的操作。 正如亨利·斯宾塞(Henry Spencer)所说的那样,“如果你对编译器撒谎,就会报复。”

请注意,不仅仅是减法的结果是未定义的,它是评估它的程序的行为


哦,我提到行为未定义吗?

实际上,程序的行为是不确定的。 您的平台/编译器上的输出恰好1 ,但它可能很容易成为其他东西。

此代码表现出未定义的行为,因为指针算法仅在操作数位于同一数组或结构中时定义。

值1是因为编译器在内存中将ab放在一起。 另一个编译器可以做不同的事情 实际上,相同的编译器可以在下次更改代码时执行不同的操作。

C编译器知道每种类型的大小。 例如,假设P是一个引用address 0x0010的int指针。 如果将P加1(P ++或P = P + 1),则P的值为0x0014

关于你的问题, ab变量声明为tandems,在physical memory它们串联,并且每个变量的头部与其他变量有4 bytes difference 。 在这种情况下,编译器知道int大小是4个字节。 当你减去2个int指针时,编译器divide the result by 4