原创 指针,数组,变量参数传递的一点总结

2013-3-14 16:31 1130 8 12 分类: 消费电子

 

测试代码:
#include
int add(int sum, unsigned char *p, unsigned char u8Len)
 {
     while(u8Len > 0)
     {
         sum += *p;
         p++;
         u8Len--;
     }

     return sum;
 }

 int main(int arg, char **argv)
 {
     unsigned char au8Temp[6] = {2, 3, 4, 5, 6, 7};
     unsigned char u8Sum = 0;
     unsigned char u8Len   = 6;
     unsigned char *pTemp = au8Temp;
 
     u8Sum = add(0, au8Temp, u8Len);
     printf("u8Sum: %d\n", u8Sum);
     u8Sum = add(0, pTemp, u8Len);
     printf("u8Sum: %d\n", u8Sum);
     return 0;
 }  
关于函数传递的值传递与指针传递。
 
这里对于传递的参数而言都是值传递,
因为在调用被调函数时,被调函数的入参已经分配了栈空间,这个时候传过来的参数就是将值写进这个这个被调函数的栈内存单元中(红色部分有错误,修正见注释3)。
这个时候可以这样理解,对于传递的参数是变量(对于变量的解释见注1)的,取其内容传递给被调函数的入参,即写入入参的栈地址空间;对于传递的参数是常量(对于常量的解释见注2)的,直接将此常量写入入参的栈地址空间。
所以这里的指针传递,实质仍是值传递。
 
传递数组名,常量,变量,指针变量的情况如下:
u8Sum = add(0, pTemp, u8Len);
(gdb) p au8Temp                              --数组中的内容,数组名是数组的首地址。
$1 = "\002\003\004\005\006\a"
(gdb) p &au8Temp                            --对数组名取地址,等于数组所在的首地址。
$2 = (unsigned char (*)[6]) 0xbffff458
(gdb) p u8Len                                    --变量u8Len的内容 
$3 = 6 '\006'
(gdb) p &u8Len                                  --变量u8Len的地址
$4 = (unsigned char *) 0xbffff45f "\006X���\200��������\226\237"
(gdb) p pTemp                                  --指针变量pTemp的内容
$5 = (
    unsigned char *) 0xbffff458 "\002\003\004\005\006\a\033\006X���\200��������\226\237"
(gdb) p  &pTemp                              --指针变量pTemp的地址
$6 = (unsigned char **) 0xbffff460
(gdb) s                                             --进入被调函数
add (sum=0, 
    p=0xbffff458 "\002\003\004\005\006\a\033\006X���\200��������\226\237", 
    u8Len=6 '\006') at test_parameter.c:7
7          while(u8Len > 0)
(gdb) p sum                                      --入参sum的内容
$7 = 0
(gdb) p &sum                                    --入参sum的地址(add函数的栈空间)
$8 = (int *) 0xbffff440
(gdb) p p                                           --入参p的内容
$9 = (
    unsigned char *) 0xbffff458 "\002\003\004\005\006\a\033\006X���\200��������\226\237"
(gdb) p &p                                         --入参p的地址    (add函数的栈空间)
$10 = (unsigned char **) 0xbffff444 
(gdb) p u8Len                                     --入参u8Len的内容
$11 = 6 '\006'
(gdb) p &u8Len                                   --入参u8Len的地址(add函数的栈空间)
$12 = (unsigned char *) 0xbffff434 "\006/�"
 
注:
1.指针也是变量,即指针变量,数组名是地址常量。数组和指针不一样。一般变量默认表示是在变量地址上加上*号,取其内容。而取其地址时,反而要加&取地址符了。指针变量比一般变量麻烦就在于它的内容还是一个地址,需要我们自己再加一个*号,才能取到真正的内容。
2.有const关键字的还认为是变量,只读变量。数组名属于常量。数组名对其取地址,还是其本身。
3.关于传入参数,是在主调函数的栈内存中,而不是在被调函数的栈内存中。
 
内存分布如下:
传入参数                               (有可能被优化到寄存器中)
call指令的下一条指令的地址
Frame Pointer
------------------------------------   主调函数和被调函数的栈内存分界
局部变量
PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户1560571 2013-3-15 11:16

感觉不错

用户1610239 2013-3-15 10:07

学习了

1989tie_959541171 2013-3-15 07:57

呵呵,当时复制过来的时候,没注意到红色消失了。谢谢小编!想到如果修改,又会生成新的博文。在这里给出修正:这个时候传过来的参数就是将值写进这个这个被调函数的栈内存单元中。是这句话有问题。它的正解在注释三中,重新描述了。但是下边的那个内存分布有问题,正解在:http://forum.eet-cn.com/BLOG_ARTICLE_16398.HTM

用户1602177 2013-3-14 16:32

博主,没有标红色啊~~
相关推荐阅读
catch2000 2015-07-19 11:44
信号线小电阻的作用
在一块新的PCB上,测试系统能否正常运行的时候,发现系统上电后没有正常启动。  系统框图如下:   在上电的时刻,CPU A(GPIO电平2.6V)会向串口发送启动日志数据,CPU A启动后,...
catch2000 2015-07-05 17:04
协议设计中ACK机制的影响
在TCP/IP中,延时ACK和Nagle算法。  TCP为了同时处理成块数据(通常为512字节的用户数据)和交互数据(通常用户数据比较少,例如不大于10个字节),采用了延时ACK和Nagle算法...
catch2000 2015-05-23 15:48
话说物联网操作系统
最近好多家都宣布推出自己的物联网操作系统。   1. Google将要在Google I/O大会发布的Brillo; 2. 三星推出的Artik芯片搭载Mentor Graphics的...
catch2000 2015-03-31 23:52
不要采用异或来交换两个变量
在进行两个变量的时候,经常会看到有些书误人子弟的推荐使用异或的方式: 方式一 {   x = x ^ y;   y = x ^ y;   x = x ^ y; } 而不是...
catch2000 2014-10-09 07:28
为什么要测试先行
在产品的研发过程中,测试一项至关重要。不论是软件还是硬件。   软件的测试先行,在研发过程中,就做到质量的保证,因为在出现Bug的时候,容易定位Bug,而且即使是在客户端出现Bug,也能够...
catch2000 2014-10-09 07:26
C语言的面向对象编程(一)
一、前言 对于编程而言,重要的是解决问题的方式,而不是语言本身。面向对象与面向过程是解决问题和思考问题的方式。C语言常说是面向过程开发的语言,因为其缺少很多对于面向对象特性的支持。但,这并不影...
EE直播间
更多
我要评论
4
8
关闭 站长推荐上一条 /3 下一条