求解一个C语言问题。
代码如下,p++是先和p结合后再++,为什么输出结果和*p一样,都是10呢?
#include<stdio.h>
int main()
{
int x[]={10,20,30,40,50};
int *p;
p=x;
printf("%d",*p++);
return 0;
}
因为 * 和 ++ 优先级一样,所以第7行保持从左往右运算
先 * p 此时就是 取到了第一个元素 10;
然后p++ 即指针后移一位。
即第7行等同于:tmp= * p ; p=p+1 ; printf("%d", tmp);
x
,其中包含了5个元素:10, 20, 30, 40, 50。p
。p
指向数组的第一个元素 x
。printf
函数输出 p
所指向的第一个元素的值(即10),并将 p
的值加1。由于是后缀自增运算符 (++
),所以此时 p
指向的是数组的第二个元素(即20)。return 0
语句结束程序。p++
实际上是在先使用 p
所指向的值(即10),然后再将 p
的值加1。如果想要在使用值之前先加1,应该使用前缀自增运算符 ++p
。*(p++)这种写法尽量不要这样写,容易引起歧义,编译器实际上还是按照*p++来处理。
因为文章开头提过,运算符*和++都属于单目运算符,两者的优先级是一样的,结合性的方向是从右到左。
然后有些人会认为这个表达式的运算顺序是:p先自身+1,然后进行解引用。其实这种想法是错误的。
正确的运算顺序应该是首先解引用指针变量p,然后p在自身加1。
之所以不按照从右向左的结合性,是因为++自身的特性引起的,我们在前面已经讲过。
根据参考资料中的内容,可以得知指向一维数组的指针本质上是指向一块连续内存空间的指针。假设有一个一维数组 arr
,指针 p
指向这个数组,执行 p++
后,指针 p
就指向了一维数组 arr
中的下一个元素(也就是指向了连续内存空间中的下一个地址),因此 *p
访问的是这个下一个元素的值。因为数组 arr
元素间的间隔是相等的,因此 p
每次自增相当于向后移动了一个元素的距离,这也是 p++
和 *p
输出结果一样的原因。
如果是多维数组,指向子数组的指针加 1 后指向的下一个元素不一定是连续存储空间中的下一个地址,这时候 *p
访问的就不是子数组中下一个元素的值,需要根据实际情况来理解和处理。
针对指向一维数组的指针问题,可以结合以下示例代码进行理解:
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;
printf("%d\n", *p); // 输出 10,指向 arr[0]
p++;
printf("%d\n", *p); // 输出 20,指向 arr[1]
return 0;
}
在代码中定义了一维数组 arr
,长度为 5,初始化了一些整型数据。在 main
函数中声明了一个指向整型变量的指针 p
,并将 arr
数组的首地址赋值给了它,也就是 p
指向了数组 arr
中的第一个元素,即 arr[0]
。根据 C 语言数组的地址连续性,p
每次自增相当于向后移动了一个元素的地址,因此 p++
之后,p
指向了数组 arr
中的第二个元素,即 arr[1]
,而输出 *p
得到的数值也变成了 20
,与 p++
前输出的第一个 *p
输出数值 10
不同。