鱼C论坛

 找回密码
 立即注册
查看: 1736|回复: 11

[已解决]关于复杂声明

[复制链接]
发表于 2019-5-14 18:50:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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

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

不太能理解,麻烦大家帮忙看看。
#include <stdio.h>
void main()
{

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

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

                printf("%s",p[0][0]);
                }
   
最佳答案
2019-5-14 23:00:52
本帖最后由 Croper 于 2019-5-14 23:15 编辑
您说的p[0][0]是指针的地址我能理解,把他解引用不就是指针变量存放的地址吗

不是,

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

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

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

再说回来,你写出类似于printf("%s",*p[0][0]);这个语句时,这里隐藏了一个类型转换,写全是这样,printf("%s",(char*)*p[0][0]);
于是,你就把一个一个指针的最后一个字节前面扩充0的值当成了指针原来的值,最后当然没法得到你想要的结果
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-5-14 19:55:34 | 显示全部楼层
本帖最后由 Croper 于 2019-5-14 20:09 编辑

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

话说你为什么总是问这种纠结问题,有这个功夫都能学很多东西了。到时候再回来看这些不更好么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-14 21:31:48 | 显示全部楼层
本帖最后由 YiMingC 于 2019-5-14 21:51 编辑
Croper 发表于 2019-5-14 19:55
既然line1 ,line2都是数组,p[0],p[1]也是数组,那么原程序不是在拿数组给数组赋值么,C语言显然不允许这么 ...


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

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

我老觉得自己学的不够扎实,数组和指针这些东西不掌握彻底怕自己以后全乱套了...麻烦您了~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-14 21:57:02 | 显示全部楼层
本帖最后由 Croper 于 2019-5-14 22:01 编辑
YiMingC 发表于 2019-5-14 21:31
原来如此,您给出的定义我可以理解了。感谢~

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


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

然后关于这些复杂的定义一般都是typedef掉的,谁有空去看一堆星星框框的。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-14 22:04:25 | 显示全部楼层
Croper 发表于 2019-5-14 21:57
非要说的话p是个指针的二维数组,你是在给这个长度为35的数组的前7个元素赋初始值。解出来的p[0][0]其 ...

解出来的p[0][0]的类型确实是char*,但是字符串在打印的时候不是就是给一个地址就可以了吗...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-14 22:11:58 | 显示全部楼层
本帖最后由 Croper 于 2019-5-14 22:17 编辑

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

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

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

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

话说c++里再来个引用,然后指针的引用,引用的指针,指针的数组的引用,岂不是要炸。。(小声)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-14 22:17:11 | 显示全部楼层
这样也可以
另外,不要纠结这类问题了

p是一个数组,有7个元素,每一个元素都是一个指针,这个指针指向一个数组,指向的这个数组有5个元素,每一个元素都是一个指针,这个指针指向char
#include <stdio.h>

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

        printf("%s\n", (*p[0])[0]);
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-14 22:37:48 | 显示全部楼层
本帖最后由 YiMingC 于 2019-5-14 22:39 编辑
Croper 发表于 2019-5-14 22:11
又来了。。
p[0][0]的类型是char*,但实际的值是指针的地址,不是指针本身。。明白么
然后你如果直接解引 ...


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

这段不是太理解...
您说的p[0][0]是指针的地址我能理解,把他解引用不就是指针变量存放的地址吗...最后要得到的不就是这个地址吗...char**类型是指向指针的指针吗...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-14 22:38:39 | 显示全部楼层
人造人 发表于 2019-5-14 22:17
这样也可以
另外,不要纠结这类问题了

这个我可以理解,但是类型转换的那个有点蒙圈...这次纠结完应该能有一段不纠结了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-14 22:44:42 | 显示全部楼层
Croper 发表于 2019-5-14 22:11
又来了。。
p[0][0]的类型是char*,但实际的值是指针的地址,不是指针本身。。明白么
然后你如果直接解引 ...

这个4字节是哪里来的啊...而且为什么直接解引用会是最后一个字节啊 (问题一个接一个)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-14 23:00:52 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Croper 于 2019-5-14 23:15 编辑
您说的p[0][0]是指针的地址我能理解,把他解引用不就是指针变量存放的地址吗

不是,

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

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

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

再说回来,你写出类似于printf("%s",*p[0][0]);这个语句时,这里隐藏了一个类型转换,写全是这样,printf("%s",(char*)*p[0][0]);
于是,你就把一个一个指针的最后一个字节前面扩充0的值当成了指针原来的值,最后当然没法得到你想要的结果
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-5-14 23:17:49 | 显示全部楼层
Croper 发表于 2019-5-14 23:00
不是,

比如说这里有一堆数据

好吧,基本上理解了,差不多先够用了,谢谢啦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-3 19:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表