通过一个swap函数来介绍指针和c语言值传递的特性。

#include<stdio.h>
void swap(int a ,int b);
void swap1(int* p1, int* p2);
int main(){
    int a=5,b=6;
    swap( a,  b);
    printf("a=%d,b=%d\n",a,b);
    int x=5,y=6;
    int *p1=&x,  *p2=&y;
    printf("&p1=%p\n",&p1);
    printf("x=%d y=%d\n",*p1,*p2);
    printf("zhizhen1=%p,zhizhen2=%p\n",p1,p2);
    swap1( p1, p2);
    printf("x=%d,y=%d\n",x,y);
    printf("zhizhen1=%p,zhizhen2=%p\n",p1,p2);
}
void swap(int a,int b){
    int c;
    c=a;
    a=b;
    b=c;

}
void swap1(int* p1,int* p2){
    int temp= *p1;
            printf("副本&p1=%p\n",&p1);
            printf("temp=%d,*p1=%d,*p2=%d\n",temp,*p1,*p2);
            printf("p1=%p,p2=%p\n",p1,p2);
    *p1=*p2;  

                 printf("temp=%d,*p1=%d,*p2=%d\n",temp,*p1,*p2);    printf("p1=%p,p2=%p\n",p1,p2);
    *p2=temp;    

                printf("temp=%d,*p1=%d,*p2=%d\n",temp,*p1,*p2);    printf("p1=%p,p2=%p\n",p1,p2);
}


使用指针可以顺利交换xy的值,而普通函数不可以,另p1指针存储的是x的地址  *p1是按照p1的地址取出对应地址的数据,*p1=*p2是交换值,从程序输出的内容来看,两个指针的地址从未改变过,值得指出的是,对于普通函数swap来说,是创建了一个副本,在这个副本中交换了ab的值,但是这个交换后的数据无法传递出去,如果再swap里面prinft ab的值,你可以看到那它确实是被改变的,对于利用指针的swap1来说,它是直接打开了存储xy信息的地址,把这个地址内的数据改变了,这个地址与swap1外面xy地址是相同的,一旦内部的值发生了改变,那就均发生了改变,所以才能起到全局交换xy值的作用,两个函数的区别是 一个是在副本内操作,一个是直接在储存对应数据的源地址操作,源地址数据改变那全局就发生改变,


​​指针传递的本质是值传递(地址值的传递)​​:
调用 swap1(p1, p2)时,实际传递的是指针变量存储的​​地址值​​
函数收到的是地址值的​​副本​​,所以 swap1()的 p1和 main()的 p1是两个不同的变量(地址不同)
​​地址副本的威力​​:
虽然指针变量本身不同(存储在不同的内存位置),但它们​​存储的地址值相同​​
相同的地址值 → 指向同一个内存位置 → ​​共享同一个数据实体​​
所以通过 *p1和 *p2操作的实际上是同一个物理内存
​​修改的是目标数据,不是指针本身​​:
你的 printf输出显示:p1和 p2的值在函数执行前后​​始终不变​​
但 *p1和 *p2的值(也就是它们指向的数据)​​发生了改变​​
这正是因为交换操作修改的是​​指针指向的内存​​,而不是指针变量本身

c语言函数的调用本质是值传递 如void swap(int a, int b,相当于是把ab的数值传递了进去 而非是把变量传递了进去。 在函数内部实际上是开辟了一个额外的地址空间存储副本(可以看到外部的指针地址和函数内指针地址并非同一个地址【这里指的是存放指针的地址】,验证了c语言函数值传递建立副本的特性),任何函数内任何操作都是在这个副本上进行的而与外界无关,而指针的出现利用地址这一指引牌直接找到存储外部全局变量的地址,直接修改这个地址上的数,就绕开了c语言值传递副本的特性。【指针的话,其实就是用来存放地址数据的一个元素类型,如0001地址上存储着a=1的数据,用指针p指向这个地址,实际上就是指针p这个变量存储了0001这个地址数据,*p就可以根据这个地址信息去找到对应的位置,取出a=1这个数据本身,既然p为一个数据元素类型,那么它本身也需要一个地址信息来存放他存储的信息 假设p存放在了0002这个地方,那么在0002的地址信息上就存放着0001这个数据,只不过0001地址存放的是一个数据,0002存放的是地址数据,之所以要叫指针,实际上是为了程序能够理解0001是个地址信息数据,而非一串普通的数据0001,把指针p直接为一个用来存放地址信息的特殊的数据元素类型即可】.

附上程序执行后的输出内容:
a=5,b=6
&p1=000000769f5ff670(外部指针的地址)
x=5 y=6
zhizhen1=000000769f5ff67c,zhizhen2=000000769f5ff678


副本&p1=000000769f5ff650(函数内部指针地址,可以看到内外指针的地址是不一样的,c语言的值传递特性)
temp=5,*p1=5,*p2=6
p1=000000769f5ff67c,p2=000000769f5ff678(内外指针存放的地址信息(即指针所指向的地址是相同的,依据地址这个指路牌就可以找到需要修改数据的地方)
temp=5,*p1=6,*p2=6
p1=000000769f5ff67c,p2=000000769f5ff678
temp=5,*p1=6,*p2=5
p1=000000769f5ff67c,p2=000000769f5ff678
x=6,y=5
zhizhen1=000000769f5ff67c,zhizhen2=000000769f5ff678
 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐