(转帖)二维数组作为实参时

  1. void foo() 
  2. {
  3.       char str[][20] = { “mik”, “fanny” };
  4.       foo1(str);        
  5.       foo2(str);
  6.       foo3(str);
  7.       foo4(str);
  8. }
复制代码


我们首先了解str这个二维数组的的内存布局是如何的:
str 将在 foo的堆栈上分配了一块2*20 (40 bytes)的连续区域:假设str 的地址为: 0xbf8179f8。

/* 
以 char ** 类型, 作为形参时, 那么是对 char[][20]二维数组造型为char **类型,是对0xbf8179f8这地区域施行 char **类型的操作
*/

  1. 一、
  2. void foo1(char **str)
  3. {
  4.        /* 此时,str的值为 0xbf8179f8。是的,
  5.       我们无法正确用 char ** 的操作来操作0xbf8179f8这块区域   
  6.       *str 提领的是0xbf8179f8里的值,也就是:0x6b696d,也就是字符串”mik”在内存中的值。
  7.       **str 操作更是提领内存地址为0x6b696d 里的值,这个值,我们不知道是什么。
  8.      */

  9.                             //所以:
  10.      puts(*str);     // 是打印内存地址为 0x6b696d里的内容,出错!
  11.      puts(str[0]);         // 等价于:*(str+0) 也就是等价于: *str。 出错!
  12.      puts(**str);    // 更不知是什么东东!出错!

  13.      puts((char *)str)); // 那么,我们只能强行,将str 造型为 char *来打印, OK!
  14.                                    // 这样,打印的是 “mik” 这个字符串。
  15.      puts(&str[0]);    // 或者这样,抵消一次提领动作,&*str。产生一个警告信息。

  16.         /* 更进一步, 在这里,
  17.            我们根本无法通过 类型为 char ** 的str指针来读取 “fanny”字符串的值 
  18.         */
  19.        puts((char *)(str+1));     // 结果不对,打印的是 0xbf8179f8 + sizeof(char *)里的值
  20.       puts(&str[1]);              // 同上!
  21. }
复制代码



二、
/* 对 0xbf8179f8 内存块施行 char [] 的操作 */
  1. void foo2(char *str[])
  2. {
  3.                            /* 一样,这里, str 的值是 0xbf8179f8 */
  4.        puts(str[0]);         // 等价于:*(str+0)是提领 0xbf8179f8的是值 0x6b696d。
  5.                     //这里的作用是打印出 0x6b696d 内存的内容,所以这里将出错!!!
  6.       puts(str[1]);   // 等价于:puts(*(str+1)),也就是打印: 0xbf8179f8+sizeof(char*),
  7.                        // 也就是: 0xbf8179fc里的值,这是一个0 值

  8.       puts((char*)str);  // 同样,只能强行造型为 (char *)进行打印出 “mik”的字符串

  9.                        /* 所以,我们无法通过 类型为 char *str[]的数组,进行操作 */
  10.                                 /* 就算你把参数类型定义为: char *str[20] , 
  11.                         也无济于事,编译器根本不需要这个具体的参数值 */
  12. }
复制代码



三、
/* 造型为 char (*str)[20] */
  1. void foo3(char (*str)[20])
  2. {
  3.          puts(str[0]);    // 结果如何呢?同样,这里的 str 的值等于 0xbf8179f8。
  4.                         // str[0] 等价于 *(str+0) 也就是 *str
  5.                                    // 由于 str 是一个指向数组的指针。
  6.                         // 所以在这里。0xbf8179f8里的内
  7.                         // 存里装的是数组的地址值。所以 (0xbf8179f8) 里的值,还是
  8.                         // 0xbf8179f8, 并不是 0x6b696d 
  9.                                    // 所以这里是正确的。
  10.                    // 可以作个实验,printf(“%x\n”, str[0]); 结果是: 0xbf8179f8。

  11.          puts(str[1]);    // str[1] 等价于 (str+1); 也就是:*(0xbf8179f8+20) 
  12.                       // 提取 0xbf8179f8+20 里面的值。也就等于是0xbf817a0c里的值。
  13.                          // 而 0xbf817a0c里的值是一个数组的地址。也等于 0xbf817a0c。
  14.                         // 即 字符串“fanny”的首地址。

  15.          /* 通过, 数组指针。我们可以正确操作数组实参 */
  16. }
复制代码


四、 
  1. void foo(char str[][20])
  2. {
  3.           puts(str[0]);     // 同样: str的值是: 0xbf8179f8
  4.                                          // 同样:str[0] 等于 *(str+0), 也就是 *str
  5.                                         // 同样由于 *str 里的值是一个数组值。
  6.                            // 也就是说:0xbf8179f8里的值是0xbf8179f8
  7.                                          // 正确! 结果是:mik
  8.         puts(*str);        // 结果同 puts(str[0]) 一样。
  9.         puts(str[1]);       // 原理同上。结果是: fanny
  10.         puts(*(str+1));    // 结果是: fanny 。 正确
  11. }
复制代码




通过以下四个例子。不难看出:

char **str  等价于 char *str[]
char  (*str)[20]  等价于 char [][20];


当二维数组作为实参时,使用 char (*str)[20] 与 char [][20] 作为形参才是正确的用法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值