开发者社区> 问答> 正文

双指针直接指向一个字符串的问题?报错

正常的开发情况下,我们不会这样写

char **prgv ="liujun";  //1

正确的写法应该是

char *p ="liujun"; 
    char **cp = &p;   //2

或者

char *ar[] ={"11","12",NULL};
CHAR **prgv=ar;

我现在故意用第1种写法来测试,如下图,标红的地方是命令执行情况。

从运行结果来看,gcc编译的时候会报警,但是没有报错。

第2个标红的地方是运行,第3个标红的地方是部分代码

从运行结果来看,我发现双指针变量prgv中存储的地址就是字符串"liujun"的首地址(换句话说,就是双指针变量prgv指向的地址就是"liujun"的首地址)

运行的最后一行代码是报错了,我当初预测这个地方应该会打印"liujun"的首地址,我是受二维数组的思想启发的,在二维数组中,比如a[0][0] 的地址等同于a[0]的地址也等同于a的地址(双指针是可以指向二维数组的),为什么我这样弄,就不可以呢?

 

 

 

展开
收起
爱吃鱼的程序员 2020-06-06 20:53:31 518 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB
                        <p>二维数组和双重指针是两码事,分开理解。</p>
    

    二重指针是指向指针的指针,解引用指向指针的指针得到的是指针,中间走了两次间接。

    int main()
    {
      int a=1;
      int *p=&a;
      int **pp=&p;
    }

    以上例来说,pp储存的是 p 的地址,p储存的是 a 的地址,解引用pp得到的是p,p指向a。

    你的代码里用的是字符串,那么再考虑字符串的情况下又是怎么一回事。

    int main()
    {
      char *pointer_to_str="abc";
      char **pointer_to_pointer_to_str = pointer_to_str;
      return 0;
    }

    简单分析,双重指针解引用后得到的是指针,换句话说,你解引用了一个指向"abc"的指针,然后把内存里的 "abc" (0x61626300)当成了一个指针,传递给了printf函数,printf函数在访问0x61626300这个地址的时候就出错了。

     

    二维数组不同于双重指针,以原始数组而言,无论你写几个维度的数组,int a[][][][],它都是一段连续内存,在数组退化的情况下,它也是退化成普通指针 int* 而不会变成 int ****。把二维数组理解成双重指针是错的,它本质上没有两次间接的过程,它索引元素的时候没有 Addr1=>Addr2=>element 这样的过程,而是 Addr1 + Row * Length + Column => Element

                                回复 <a class="referer" target="_blank">@uniqptr</a>  : 谢谢。
                        
    
                                回复 <a class="referer" target="_blank">@tcxu</a>  : 如果你说的字符串指针是`char*`而不是之前提到的`char**`,那么*((char*)p)得到的是一个char没错。如果是char**并且指向"a"的话,即使"a"只有两个字节,但它还是会尝试访问以"a"开头的四个字节,并把它当成一个指针值。
                        
    
                                回复 <a class="referer" target="_blank">@uniqptr</a>  : 谢谢答复。如果字符串长度是 1,比如"a", 而目标平台指针长度是4, 那就无法读取了。所以我认为,一个字符串指针的解引用,是这个字符串第一个字符的ASCII码的值。对吗?
                        
    
                                回复 <a class="referer" target="_blank">@tcxu</a>  : 看目标平台指针长度,也就是sizeof(void*)。
                        
    
                                回复 <a class="referer" target="_blank">@uniqptr</a>  : 谢谢答复。如果不是"abc", 而是"abcdefg",连续内存从'a'开始,0x61 0x62 0x63 0x64.. 0x00, 共8个字节,那么强制转换又将是多少?
                        
    
                        <p>有人吗?</p>
    
                    
    
                        <ol>
    <li>你的这个情况,字符串“Liujun”的地址,即字符串第一个字符的地址,可以用 :&*prgv,prgv,或者 "Liujun", 来表示。</li>
    <li>最后出错的原因是,若要打印出这个字符串,应当用以上任何一种形式来表示字符串的地址,而不是用 *prgv (字符指针的地址),即</li>
    
    printf("*prgv:%s\n", prgv); 
    printf("&*prgv:%s\n", &*prgv); 
    printf("*prgv:%s\n", "Liujun"); 

     

                        <p>既然</p>
    

    printf("*prgv:%s\n", prgv);  打印出正确结果,意味着prgv就是指向了liujun的首地址,

    *prgv 的结果就是l

    而 printf("*prgv:%s\n", *prgv); //其含义是把l当做地址来再次解析,所以会报错。

    2020-06-06 20:53:48
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载