有以下程序
#include <stdio.h> #include <stdlib.h> void fun(int *p1, int *p2, int *s) { s = (int *)malloc(sizeof(int)); *s = *p1 + *(p2++); } int main() { int a[2] = {1, 2}, b[2] = {10, 20}, *s = a; fun(a, b, s); printf("%d \n", *s); }
程序运行后的输出结果是?
答案是C 当调用fun(a,b,s);传进的参数实际上是:&a[0], &b[0], s变量的值(实际上也就是&a[0])
现在把fun的形参换个名字 fun(int *p1, int *p2, int *p3)
进入fun时 p3 = s ,即p3 = &a[0].
调用malloc时返回的值是一个int*,实际上 p3 = malloc返回的新指针p4
*p3=*p1+*(p2++) 即 *p4=*p1+*(p2++);
p4并不是s,算出来的值赋值到malloc返回的指针p4指向的内存了。
若想p3(即s)拿到计算的值,把s=(int*)malloc(sizeof(int) );这句去掉即可得到11。
#include <stdio.h> #include <stdlib.h> void fun ( int ﹡pl,int ﹡p2,int ﹡s ) { // s = (int﹡) malloc(sizeof(int)); 这行注释掉的结果是11,所以我觉得不是值传递的问题,而是s新在堆上新申请了内存 ﹡s = ﹡pl + ﹡(p2++ ); 如果没有这句,*s是能改变a[1]的值得 } main( ) { int a [2] = {l,2],b [2] = {10,20},﹡s = a; fun (a,b,s); printf ( "%d \n", ﹡s);
} a [2] = {l,2],b [2] = {10,20},﹡s = a; fun (a,b,s); printf ( "%d \n", ﹡s);}
后缀递增递减比前缀优先级高,从左到右。
比如
1 2 | int arr[5] = { 1,3,5,7,9 }; int *p = arr; |
*++p:p先自+,然后*p,最终为3
++*p:先*p,即arr[0]=1,然后再++,最终为2
*p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
(*p)++:先*p,即arr[0]=1,然后1++,该语句执行完毕后arr[0] =2
*(p++):效果等同于*p++
原因是在fun()函数中,虽然传入了指针s的地址,但在函数内部对s进行动态内存分配并赋值后,并没有将分配的内存地址回传给main()函数中的指针s。因此,在main()函数中打印*s时,仍然输出的是初始的a数组中的第一个元素的值(即 1)。
具体来说,函数fun()中的语句s = (int *)malloc(sizeof(int));分配了一块动态内存,然后通过*s = *p1 + *(p2++);计算了p1指向的值和p2指向的值之和,并将结果赋值给了动态内存所指向的地址。但由于s是按值传递(在函数中只修改了拷贝),所以这个修改不会影响到main()函数中的指针s。
要在fun()函数中修改main()函数中的指针s,可以通过传递指向指针s的指针来实现。例如,函数原型可以改为void fun(int *p1, int *p2, int **s),而在函数内部进行动态内存分配和赋值的语句可以改为*s = (int *)malloc(sizeof(int));和**s = *p1 + *(p2++);。这样,指针s就会被修改,并且可以在main()函数中正确输出修改后的值。