printf函数中表达式的评估

时间:2018-03-01 15:21:01

标签: c compiler-optimization

请看下面的代码

#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?是否是由于计算优化?

2 个答案:

答案 0 :(得分:5)

首先,你所做的是错的。如果指针算法指向同一数组对象的元素或指向数组对象的最后一个元素的指针,则指针算法有效。所以它是未定义的行为。

在你的情况下,减法返回一个与另一个的距离 - 基于指向的对象的类型,这里intsizeof int正在4个字节,返回1表示1 int分隔。 (与4字节相同 - 可以从ab的值推断出来。

来自§6.5.6¶9C11标准(这指出了上述两点)

  

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

您正在使用%d格式说明符打印地址。您应该使用带有参数%p的{​​{1}}格式说明符。并且从不考虑取消引用这些指针,因为它将是未定义的行为。

答案 1 :(得分:1)

  

我无法理解为什么(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进行编译,然后改进代码以获取 no 警告。详细了解undefined behavior(您的代码有一些),并且scaredUse the gdb debugger(或者您可以使用的任何其他调试器)。阅读您正在使用的每个标准函数的documentation(以及其他库中的每个外部函数),特别是printf

稍后,请考虑阅读C11标准的内容,例如n1570(草案实际上是标准文本)。

关心portability(对不同的计算机或编译器)。

根据定义,compiler optimization不应更改观察到的行为和程序的semantics