#include<stdio.h>
int main()
{
float a=10;
float* p=&a;
printf("%u\n",p);
p=p+3;
printf("%u",p);
}
执行这个程序后,我得到了2个内存地址作为输出,latter的值比前者大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。可能是什么原因呢?
这就是指针运算的原理。它被设计成在数组上工作。
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
指向一个单一的float(它的内存布局与1个float的数组相同)。使一个指针指向对象的边界之外是一个错误。在典型的PC编译器上,你只是默默地得到一个无效的指针;极少数的实现会在计算出无效的指针后立即检测到它,并以错误中止程序。
用以下方法打印指针值 %u
也是一个错误。在实践中,它可能会工作,打印垃圾,或者崩溃,这取决于你的编译器和指针的大小是否与 unsigned int
. 任何一个半路出家的编译器都会警告你说 printf("%u", p)
是不正确的;如果你的版本没有,请确保启用它的有用警告(例如 gcc -O -Wall
如果你使用的是GCC)。)
在C语言中,只有三种类型的指针运算是允许的。
标准说。
2 对于加法,两个操作数都应具有算术类型,或 一个操作数应是指向一个完整对象类型的指针,另一个操作数应是整数类型. (递增相当于加1)。
3 对于减法,下列情况之一应成立。
- 两个操作数都是算术类型; -- 两个操作数都是指向兼容的完整对象类型的限定或非限定版本的指针。;或------------------------------- 左边的操作数是指向一个完整对象类型的指针,右边的操作数是整数类型。.
任何其他算术操作都是无效的,并将调用未定义的行为。请注意,打印地址的正确指定符是 %p
.
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