请看下面的代码
#include<stdio.h>
int main(void){
int *ptr,a,b;
a = ptr;
b = ptr + 1;
printf("the value of a,b is %d and %d respectively\n",a,b);
printf("the value of a is %d \n",(ptr));
printf("the value of b is %d \n",(ptr+1));
printf("the value of (ptr+1)-ptr is %d \n",(ptr+1)-ptr);
return 0;
}
输出:
the value of a,b is 0 and 4 respectively
the value of a is 0
the value of b is 4
the value of (ptr+1)-ptr is 1
我无法理解为什么(ptr + 1)-ptr的值为1而不是4为4-0?是否是由于计算优化?
首先,你所做的是错的。如果指针算法指向同一数组对象的元素或指向数组对象的最后一个元素的指针,则指针算法有效。所以它是未定义的行为。
在你的情况下,减法返回一个与另一个的距离 - 根据指向的对象的类型是int
这里,sizeof int
是4
字节,它返回1
表示1
int
分离。 (意思是与4
字节相同 - 可以从a
和b
的值推断出来)。
从§6.5.6¶9C11标准(这指出了上述两点)
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素;结果是两个数组元素的下标差异......
并且您使用%d
格式说明符打印地址。您应该使用带有参数%p
的void*
格式说明符。并且从不考虑取消引用这些指针,因为它将是未定义的行为。
我无法理解为什么(ptr + 1)-ptr的值是1而不是4
不,C中的指针算术发生在与指向类型相关的单位中(不是以字节为单位)。阅读一些C编程书。
所以(ptr+1) - ptr
是1,但如果你将每个指针投射到char*
,例如通过编码(char*)(ptr-1) - (char*)ptr
,你可能得到4(假设sizeof(int)
是4)。
不要忘记在编译时启用所有警告和调试信息:如果使用GCC,使用gcc -Wall -Wextra -g
编译,然后改进代码以完全不发出警告。阅读更多关于undefined behavior(你的代码有一些)和它的scared。 Use the gdb
debugger(或您可以使用的任何其他调试器)。阅读您使用的每个标准函数的documentation(以及其他库中的每个外部函数),特别是printf。
稍后,还要考虑读取C11标准的部分,例如: n1570(草案实际上是标准文本)。
关心portability(到不同的计算机或编译器)。
根据定义,compiler optimization不应该改变你的程序的观察行为和semantics。