向指针添加一个数字

Addition of a number to a pointer

#include<stdio.h>
int main()
{  
     float a=10;
     float* p=&a;
    printf("%u\n",p);
     p=p+3;
     printf("%u",p);
}

执行该程序后,我得到 2 个内存地址作为输出,后者的值比前者大 12。

#include<stdio.h>
int main()
{  
     float a=10;
     float* p=&a;
    printf("%u\n",p);
     p=p+3.5;
     printf("%u",p);
}

我尝试将 3 更改为 3.5,但我得到了两个地址值相等的输出。我预计在这两种情况下该值至少会增加 12。 可能是什么原因?

C中只允许三种类型的指针运算:

  • 向指针添加一个整数。
  • 从指针中减去一个整数。
  • 从一个指针中减去另一个指针(它们应该指向同一个数组)。

标准说:

C11:6.5.6 加法运算符:

2 For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)

3 For subtraction, one of the following shall hold:

— both operands have arithmetic type;
both operands are pointers to qualified or unqualified versions of compatible complete object types; or
the left operand is a pointer to a complete object type and the right operand has integer type.

任何其他算术运算都是无效的,并且会调用未定义的行为。请注意,打印地址的正确说明符是 %p.

这就是指针算法的工作原理。它设计用于数组。

float array[4];
float *q;
q = array; /* Now q points to the first element of the array: q == &array[0] */
printf("%p\n", q);
q += 3; /* Now q points to the fourth element of the array: q == &array[3] */
printf("%p\n", q);

当您将一个整数添加到一个指针时,它指向数组中更多的元素。如果数组元素的大小为 N 个字节,则将 x 添加到指针会将 x*N 添加到地址。

在你的机器上,sizeof(float) 似乎是 4:你看到 x*N=12,x=3,所以 N=4。

请注意,您的代码中有几个错误。在您的程序中,p=p+3 具有未定义的行为,因为 p 指向单个浮点数(其内存布局与 1 个浮点数的数组相同)。使指针指向对象边界之外是错误的。在典型的 PC 编译器上,你只是默默地得到一个无效的指针;极少数实现会在计算后立即检测到无效指针,并以错误中止程序。

%u打印指针值也是一个错误。实际上,它可能会工作、打印垃圾或崩溃,这取决于您的编译器以及指针是否具有与 unsigned int 相同的大小。任何半途而废的编译器都会警告您 printf("%u", p) 是不正确的;如果您的没有,请确保启用其有用的警告(例如 gcc -O -Wall 如果您使用的是 GCC)。

the program contains several errors and poor programing practices

#include<stdio.h>
int main()
{  
    float a=10; // init floats with float values, so use '10.0f'
    float* p=&a;
    printf("%u\n",p); // print addresses with '%p' not '%u'
    p=p+3;        // now 'p' is pointed to some unknown area
    printf("%u",p); // print addresses with '%p' not '%u'
}

good thing the code did not 'de-reference' 'p' after 'p'
was modified, because that would have been undefined behaviour
possibly leading to a seg fault event