指针操作产生意外结果

时间:2019-12-12 06:00:17

标签: c pointers subtraction

我期望下面的代码显示4(因为浮点数是4字节),但是它显示1。有人可以解释为什么会这样吗?

#include <stdio.h>
int main()
{
    float a[4]={0.0,0.1,0.2,0.3};
    printf("%d", &a[1]-&a[0]);
    return 0;
}

2 个答案:

答案 0 :(得分:7)

首先,更改

  printf("%d", &a[1]-&a[0]);

 printf("%td", &a[1]-&a[0]);

因为两个减法的结果类型产生类型ptrdiff_t,而%td是该类型的转换说明符。

也就是说,引用C11,第§6.5.6章,减法运算符(强调我的

  

当减去两个指针时,两个指针都应指向同一数组对象的元素,   或在数组对象的最后一个元素之后; 结果是   两个数组元素的下标。 [....]在   换句话说,如果表达式PQ分别指向第i和第j个元素   如果是数组对象,则表达式(P)-(Q)的值为i−j,前提是该值适合类型为ptrdiff_t的对象。 [....]

在您的情况下,P&a[1],而Q&a[0],所以i1,而j0。因此,减法运算的结果为i-j,即1-01

答案 1 :(得分:3)

您是正确的,两个指针相距4个字节。而且,如果您减去两个整数,您将得到4。但是&a[1]&a[0]的类型为float *Pointer arithmetic in C考虑​​到所指事物的大小,因此&a[1]-&a[0]为1。

这是数组索引工作的基本方法。您可以利用它来遍历数组,而无需单独的索引,而可以终止于NaN之类的边界。

#include <stdio.h>
#include <math.h>

int main()
{
    float a[] = { 0.0,0.1,0.2,0.3,NAN };

    float *iter = a;
    while(!isnan(*iter)) {
        printf("%f\n", *iter);
        iter++;
    }
}

如果将值强制转换为unsigned int,则确实会得到4。

printf("%u\n", (unsigned int)&a[1]-(unsigned int)&a[0]);