YiMingC 发表于 2019-5-14 18:50:22

关于复杂声明

代码如下,这个本来是一道课后题,用二维指针数组的方法我可以做出来,但是想知道如果只能通过下面的方法,应该如何才能正确输出?

我编译的时候一直提示我14行的位置:warning: initialization from incompatible pointer type

我这里定义的p是 (存放(存放(字符类型指针)的数组)的数组,感觉应该没什么问题啊...但是输出却是乱码...

不太能理解,麻烦大家帮忙看看。

#include <stdio.h>
void main()
{

      char *line1 = {"########","####"," ###### ","##   ##"," ###### "};
      char *line2 = {"##      "," ## ","##    ##","##   ##","##    ##"};
      char *line3 = {"##      "," ## ","##      ","##   ##","##      "};
      char *line4 = {"######"," ## "," ###### ","#########","##      "};
      char *line5 = {"##      "," ## ","      ##","##   ##","##      "};
      char *line6 = {"##      "," ## ","##    ##","##   ##","##    ##"};
      char *line7 = {"##      ","####"," ###### ","##   ##"," ###### "};

       
      char *(p) = {line1,line2,line3,line4,line5,line6,line7};

                printf("%s",p);
                }
   

Croper 发表于 2019-5-14 19:55:34

本帖最后由 Croper 于 2019-5-14 20:09 编辑

既然line1 ,line2都是数组,p,p也是数组,那么原程序不是在拿数组给数组赋值么,C语言显然不允许这么写。
非要这样写请使用二重指针数组char **p = {line1,line2,line3,line4,line5,line6,line7};


话说你为什么总是问这种纠结问题,有这个功夫都能学很多东西了。到时候再回来看这些不更好么

YiMingC 发表于 2019-5-14 21:31:48

本帖最后由 YiMingC 于 2019-5-14 21:51 编辑

Croper 发表于 2019-5-14 19:55
既然line1 ,line2都是数组,p,p也是数组,那么原程序不是在拿数组给数组赋值么,C语言显然不允许这么 ...

原来如此,您给出的定义我可以理解了。感谢~

但是关于您说的“那么原程序不是在拿数组给数组赋值么”是体现在不能把数组作为新数组元素吗?数组作为数组元素的时候应该看成类指针?我刚刚试了试确实会有警告:从不兼容的指针类型初始化

我老觉得自己学的不够扎实,数组和指针这些东西不掌握彻底怕自己以后全乱套了...麻烦您了~

Croper 发表于 2019-5-14 21:57:02

本帖最后由 Croper 于 2019-5-14 22:01 编辑

YiMingC 发表于 2019-5-14 21:31
原来如此,您给出的定义我可以理解了。感谢~

但是关于您说的“那么原程序不是在拿数组给数组赋值么 ...

非要说的话p是个指针的二维数组,你是在给这个长度为35的数组的前7个元素赋初始值。解出来的p其实是line1的地址,也是line1第一个指针的地址,但是它的类型是(char*),所以不能直接解引用,把类型转换成(char**)再接引用应该就能得到"#######"了;

然后关于这些复杂的定义一般都是typedef掉的,谁有空去看一堆星星框框的。。

YiMingC 发表于 2019-5-14 22:04:25

Croper 发表于 2019-5-14 21:57
非要说的话p是个指针的二维数组,你是在给这个长度为35的数组的前7个元素赋初始值。解出来的p其 ...

解出来的p的类型确实是char*,但是字符串在打印的时候不是就是给一个地址就可以了吗...{:5_99:}

Croper 发表于 2019-5-14 22:11:58

本帖最后由 Croper 于 2019-5-14 22:17 编辑

又来了。。
p的类型是char*,但实际的值是指针的地址,不是指针本身。。明白么
然后你如果直接解引用,得到的值是这个指针的最后一个字节,而不是整个指针。所以需要进行类型转换,

p<====>list1
char*                  char**

*p   <====>   *(char*)list1
char(只有1个字节)      char(只有1个字节)

*(char**)p <=====> *list1
char*(4个字节)          char*(4个字节)

明白了么
不明白也没关系,反正也没啥用。。

话说c++里再来个引用,然后指针的引用,引用的指针,指针的数组的引用,岂不是要炸。。(小声)

人造人 发表于 2019-5-14 22:17:11

这样也可以
另外,不要纠结这类问题了

p是一个数组,有7个元素,每一个元素都是一个指针,这个指针指向一个数组,指向的这个数组有5个元素,每一个元素都是一个指针,这个指针指向char

#include <stdio.h>

int main(void)
{
      char *line1 = {"########","####"," ###### ","##   ##"," ###### "};
      char *line2 = {"##      "," ## ","##    ##","##   ##","##    ##"};
      char *line3 = {"##      "," ## ","##      ","##   ##","##      "};
      char *line4 = {"######"," ## "," ###### ","#########","##      "};
      char *line5 = {"##      "," ## ","      ##","##   ##","##      "};
      char *line6 = {"##      "," ## ","##    ##","##   ##","##    ##"};
      char *line7 = {"##      ","####"," ###### ","##   ##"," ###### "};
      char *(*p) = {&line1, &line2, &line3, &line4, &line5, &line6, &line7};

        printf("%s\n", (*p));
        return 0;
}

YiMingC 发表于 2019-5-14 22:37:48

本帖最后由 YiMingC 于 2019-5-14 22:39 编辑

Croper 发表于 2019-5-14 22:11
又来了。。
p的类型是char*,但实际的值是指针的地址,不是指针本身。。明白么
然后你如果直接解引 ...

但是它的类型是(char*),所以不能直接解引用,
把类型转换成(char**)再接引用应该就能得到"#######"了;

这段不是太理解...
您说的p是指针的地址我能理解,把他解引用不就是指针变量存放的地址吗...最后要得到的不就是这个地址吗...char**类型是指向指针的指针吗...{:5_107:}

YiMingC 发表于 2019-5-14 22:38:39

人造人 发表于 2019-5-14 22:17
这样也可以
另外,不要纠结这类问题了



这个我可以理解,但是类型转换的那个有点蒙圈...这次纠结完应该能有一段不纠结了{:5_111:}

YiMingC 发表于 2019-5-14 22:44:42

Croper 发表于 2019-5-14 22:11
又来了。。
p的类型是char*,但实际的值是指针的地址,不是指针本身。。明白么
然后你如果直接解引 ...

这个4字节是哪里来的啊...而且为什么直接解引用会是最后一个字节啊 (问题一个接一个){:10_266:}

Croper 发表于 2019-5-14 23:00:52

本帖最后由 Croper 于 2019-5-14 23:15 编辑

您说的p是指针的地址我能理解,把他解引用不就是指针变量存放的地址吗
不是,

比如说这里有一堆数据
46 69 73 6863 00 00 00

然后有一个指针指向第一个字节,然后对这个指针解引用,你会得到什么?
结果是:无法确定

因为这要视指针类型而定,
如果这是一个char* 指针,那么得到的值为0x46(F)
如果这是一个int* 指针,那么得到的值为0x68736946
如果这是一个long long*指针,那么得到的值为0x0000006368736946
如果这是一个char**指针,那么得到的值也为0x68736946,然后程序会把这个值看成一个地址,你可以继续对这个地址解引用

再说回来,你写出类似于printf("%s",*p);这个语句时,这里隐藏了一个类型转换,写全是这样,printf("%s",(char*)*p);
于是,你就把一个一个指针的最后一个字节前面扩充0的值当成了指针原来的值,最后当然没法得到你想要的结果

YiMingC 发表于 2019-5-14 23:17:49

Croper 发表于 2019-5-14 23:00
不是,

比如说这里有一堆数据


好吧,基本上理解了,差不多先够用了,谢谢啦{:10_250:}
页: [1]
查看完整版本: 关于复杂声明