向指针添加一个数字
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
#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