数组名取地址带来的问题

我们都知道数组名取地址的值和数组的首地址是同一个值,但是他们的指类是不同的,如果强转的话是会出问题的。看看下面这个程序片段:

<pre name="code" class="cpp">#include <stdio.h>

int main(void)
{
        char str[128];

        printf("str: %p\n", str);
        printf("str + 1: %p\n", str + 1);
        printf("&str: %p\n", &str);
        printf("&str + 1: %p\n", &str + 1);

        return 0;
}

int main(void){ int i = 0; char str[128]; memset(str, 0, sizeof(char) * 128); printf("str: %p\n", str); printf("&str: %p\n", &str); foo((char **)&str); return 0;}

 

从语法上讲,程序是可以编译过去的,但一运行就会出现段错误。

段错误出在foo()函数中的第三条printf语句中的 **t  表达式,其实从第二条printf语句中已经看到,*t的值为0x0, 这样再对*t做指向运算,一定是段错误。

问题出现在两点,

1.在main()函数中,str的值与&str的值虽然是相同的,但他们的所指向的内容是不同的;

str指向一个字符,也就是一个内存单元,所以(str + 1) - str 的值应该是1;

而&str指向一个数组,即(&str + 1)指向下一个数组,类似于二维数组中的行指针,所以(&str + 1) - &str 的值应该是sizeof(str),即str数组的大小。

这个可以通过下边的程序片段来验证:

#include <stdio.h>
int foo(char **t)
{
  printf("t: %p\n", t);
  printf("*t: %p\n", *t);
  printf("**t: %p\n", **t);
   
  return 0;
}

2.在foo()函数中,t 的值其实是:t == &str == str。但此时 t 是二级指针,对于表达式 (*t), 从计算机的角度来讲,它的值等于 (*str), 而且 t 的类型是char **, 所以(*t) 的类型就是char *,从这里可看出,(*str)原本的类型是char, 但这里由(*t)得到的类型却是一个指针,它占8字节(64位机器),也就是str数组的前8个内存单元,由于我们使用memset()全赋值为0,所以(*t)的值就是0x0,所以(**t)这个表达式就会出现但错误。

那如果我们在foo()函数中确实需要(*t)++,(**t)等这样的操作怎么办?

在main()函数中单独申请一个指针p,赋值为str, 然后再将&p作为参数传进去,即:

char *p = str;

foo(&p);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值