现在的位置: 首页 > 综合 > 正文

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

2014年01月26日 ⁄ 综合 ⁄ 共 2173字 ⁄ 字号 评论关闭
测试代码:
#include <stdio.h>
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
------------------------------------   主调函数和被调函数的栈内存分界
局部变量

抱歉!评论已关闭.