#include <stdio.h>
int main()
{
char str[3][15] = {"Pointer to","char","program"};
char (*pt)[15] = str; // statement A
char *p = (char *)str; // statement B
printf("%s\n",p[3]); // statement C - Seg Fault in this line
printf("%s\n",p); // working properly displaying "Pointer to"
printf("%s\n",p+1); // here it is pointing to second element of first array so displaying "ointer to"
printf("%s\n",pt+1); // printing properly "char" as expected
int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*nm)[3] = num[1];
int *n = num;
printf("n - %d\n",n[10]); // statement D
printf("nm - %d\n",nm[0][0]);
return 0;
}
我的问题:
请帮助我清楚了解数据存储机制 char数组和int数组的情况
在上面的程序中我理解指向char数组的时候 指向char的二维数组,如语句A所示 正确显示,但是当它被普通的char指针指向时 并尝试在语句C中打印char它正在获得SegFault, 相反,它应该打印'n'(第一个数组中的第三个数字字符“指针 “)所以有混淆为什么在int数组我正在适当 在语句D中元素n = 11,为什么在这种情况下(语句C)它 没有正确打印。
如果存储char数组,将如何存储数据 在下面显示的这种形式
char str[3][15] = {{'P','o','i','n','t','e','r',' ','t','o'},
{'c','h','a','r'},
{'p','r','o','g','r','a','m'}};
如果它像这样存储,那么它应该像语句D中显示的整数指针数组一样工作 请帮我指导一下这个问题,并澄清我在char和int数组存储时遇到的问题。
答案 0 :(得分:3)
让我们一步一步地查看您的代码。
char str[3][15] = {"Pointer to","char","program"};
在这里,您创建了一个包含15个char
的三个数组的数组。并且您正在使用字符串文字初始化每个char
数组。如果文字比数组短 - 最后一个元素用零填充,所以它与:
char str[3][15] = {
{'P', 'o', 'i', 'n', 't', 'e', 'r', ' ', 't', 'o', 0, 0, 0, 0, 0},
{'c', 'h', 'a', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{'p', 'r', 'o', 'g', 'r', 'a', 'm', 0, 0, 0, 0, 0, 0, 0, 0}
};
然后
char (*pt)[15] = str; // statement A
在这里,您创建pt
作为指向15个char
数组的指针,并使用str[0]
的地址对其进行初始化,即pt
指向第一个{来自char[15]
的{1}}数组。
下一步
str
不行。据我所知 - 你试图让char *p = (char *)str; // statement B
指向p
占用的内存中的第一个char
。表达式str
的类型为str
,即它是一个指向字符数组的指针,而不是指向char (*)[15]
的指针(因此你被迫使用强制转换),而且无论如何事实上char
确实指向存储str
的单元格 - 您应该以更安全的方式使用它:
'P'
char *p = &str[0][0]; // the same as "p = str[0];"
引用了str[0]
的第一个元素,即str
的类型是十五个str[0]
的数组,那么你可以引用第一个char
{1}}并将其作为地址 - char
,或者只是使用“array”类型的表达式衰减键入“指向第一个数组元素的指针”的事实,这就是&(str[0])[0]
也可以工作的原因。
让我们继续
str[0]
此行导致未定义的行为,因为格式说明符要求第二个参数为printf("%s\n",p[3]); // statement C - Seg Fault in this line
,但您传递的是const char *
。如果你想打印一个字符 - 那样做:
char
然后
printf("%c\n", p[3]); // prints "n"
这些工作得很好,因为第二个参数的类型是正确的,我们知道字符串是以nul结尾的。
printf("%s\n",p); // working properly displaying "Pointer to"
printf("%s\n",p+1); // here it is pointing to second element of first array so displaying "ointer to"
坦率地说 - 这是不正确的,因为printf("%s\n",pt+1); // printing properly "char" as expected
是“指向pt + 1
数组的指针”,但你应该传递“指向char的指针”。它应该改写为:
char
但它似乎有效,因为无论类型不兼容,两个指针都指向同一位置。
关于printf("%s\n",*(pt+1)); // or pt[1]
的下一部分。
int
以下是两个错误:int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*nm)[3] = num[1];
int *n = num;
不应该使用nm
进行初始化,因为它们具有不兼容的类型:“指向三个数组的num[1]
”与“四个数组{{ 1}} /指向int
的指针(由于腐朽)。并且int
无法使用int
进行初始化,因为它们也具有不兼容的类型。根据我对你想要的东西的猜测,它应该以下一个方式看待:
n
最后一个:
num
取消引用也是正确的并且也传递了参数,但请记住,指针的初始化不正确。
希望,我已经涵盖了你所有的问题。
答案 1 :(得分:2)
您的段错是由于您将错误的类型传递给printf。
写p[3]
您正在引用指向矩阵char
第一行的第4 str
的指针。与*(p+3)
如果你想打印第3个字符,你应该
printf("%c\n",p[3]);
如果要打印第一个C-String(矩阵的第0行),您必须:
printf("%s\n",&p[3]);
因为%s
需要char *
。
如果您为命令添加(至少对于gcc,-Wall
选项,编译器将向您显示一个好的有用警告:
test.c:8:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s\n",p[3]); // statement C - Seg Fault in this line
关于问题3,您必须注意正确的存储是:
char str[3][15] = {{'P','o','i','n','t','e','r',' ','t','o','\0'},
{'c','h','a','r','\0'},
{'p','r','o','g','r','a','m','\0'}};
由于C-String以空值终止,因此,例如,字符串"Pointer to"
将占用11
个字符
最后一件事是关于int
指针。它运行良好,因为%d
格式说明符需要int
值,而不是地址。所以写道:
printf("n - %d\n",n[10]);
完全正确,因为n[10]
取消引用num
矩阵的第11个元素,这意味着第3行的第3个元素。与*(n+10)