C语言

C语言参数传递

2018-05-08  本文已影响0人  Moclin

C语言参数传递

前言

最近复习Block相关知识,其中有个问题:block中为什么不能改变(这里值重新复制)被截获的自动变量,这个问题涉及到C语言参数传递,所以回头看了一下,并做了一些整理。

下面是C语言的几种参数传递方式:值传递、引用传递、指针传递、指针引用传递。

PS:为方便表述,以下内容的图片对内存的描述作了简化,如int类型是4个字节,指针类型是8个字节,这里统一用相同大小的一个格子表示。

1. 值传递

代码:

void func(int p)
{
    printf("\n-----------func start-----------");
    printf("\n&p : %x", &p);
    printf("\np : %x", p);
    p = 0xff;
    printf("\n-----------func end-----------\n");
}

void test()
{
    int a = 0x10;
    printf("\n&a : %x", &a);
    printf("\na : %x", a);
    func(a);
    printf("\na : %x", a);
}

输出:

&a : efbfde3c
a : 10

-----------func start-----------
&p : efbfde1c
p : 10
-----------func end-----------

a : 10

通过上面的代码及输出可知,变量a的地址为efbfde3c,值为10;通过调用func(a),通过输出可知:变量p的地址为efbfde1c,值为10。也就是说参数传递只把变量a的值传递给了变量p,此时变量a与变量p是值相同的两个不同变量,在内存不同的两个地址中,所以对变量p赋值只是修改了变量p的值,并不能修改变量a的值,如下图所示。总结一句话就是:值传递不传递变量本身,只传递变量的值。

1.png

2.引用传递

代码:

void func(int &p)
{
    printf("\n-----------func start-----------");
    printf("\n&p : %x", &p);
    printf("\np : %x", p);
    p = 0xff;
    printf("\n-----------func end-----------\n");
}

void test()
{
    int a = 0x10;
    printf("&a : %x", &a);
    printf("\na : %x\n", a);
    func(a);
    printf("\na : %x", a);
}

输出:

&a : efbfde2c
a : 10

-----------func start-----------
&p : efbfde2c
p : 10
-----------func end-----------

a : ff

与值传递不同,func的参数是int &p,表示引用传递。如输出所示,通过引用传递,变量a的地址与变量p是相同的,也就是说引用传递把a的地址传给了变量p,所以对变量p进行赋值之后,变量a的值也改变了,因为变量a与变量p实际是同一个变量。如下图所示:

2.png

3. 指针传递

代码:

void func(int *p)
{
    printf("\n-----------func start-----------");
    printf("\n&p : %x", &p);
    printf("\n*p : %x", *p);
    printf("\np : %x", p);
    *p = 0xff;
    printf("\n-----------func end-----------\n");
}

void test()
{
    int a = 0x10;
    printf("&a : %x", &a);
    printf("\na : %x\n", a);
    func(&a);
    printf("\na : %x", a);
}

输出:

&a : efbfde2c
a : 10

-----------func start-----------
&p : efbfde08
*p : 10
p : efbfde2c
-----------func end-----------

a : ff

指针传递,顾名思义,int *p表明p是一个指针变量,调用func(&a)是把变量a的内存地址传递过去赋值给指针变量p,此时指针变量p的值是变量a的内存地址,故可看到输出p为efbfde2c(变量a的内存地址)。*p是对指针p的值(即变量a的内存地址)进行取值,相当于*&a,所以对*p进行赋值也就改变了变量a的值。如下图所示:

3.png

4. 指针引用传递

代码:

void func(int *&p)
{
    printf("\n-----------func start-----------");
    printf("\n&p : %x", &p);
    printf("\n*p : %x", *p);
    printf("\np : %x", p);
    *p = 0xff;
    printf("\n-----------func end-----------\n");
}

void test()
{
    int a = 0x10;
    printf("&a : %x", &a);
    printf("\na : %x\n", a);
    int *b = &a;
    printf("\n&b : %x", &b);
    printf("\n*b : %x", *b);
    printf("\nb : %x", b);
    func(b);
    printf("\na : %x", a);
}

输出:

&a : efbfde2c
a : 10

&b : efbfde20
*b : 10
b : efbfde2c
-----------func start-----------
&p : efbfde20
*p : 10
p : efbfde2c
-----------func end-----------

a : ff

其实理解了前面的,这里也就明了了。首先把变量a的地址即&a赋值给指针变量b,指针变量b的值就是efbfde2c(后面的的输出证明了这一点)。然后调用
func(b),这里跟前面的引用传递一样道理,指针变量p实质是是指针变量b,而指针变量b的值又是变量a的内存地址,所以*p等同于*b,对其进行赋值相当于对变量a进行赋值(a = 0xff)。可见下图:

4.png
上一篇下一篇

猜你喜欢

热点阅读