#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 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数组存储情况下的问题。
发布于 2016-07-28 00:40:20
让我们一步一步地查看您的代码。
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
作为指向15char
的数组的指针,您正在用str[0]
的地址初始化它,即pt
从str
指向第一个char[15]
数组。
下一首
char *p = (char *)str; // statement B
这是不好的。据我所见-您正在尝试使p
指向str
占用的内存的第一个char
。表达式str
的类型为char (*)[15]
,即它是指向字符数组的指针,而不是指向char
的指针(正因为如此,您被迫使用强制转换),而且不管str
实际上指向存储'P'
的单元格--您应该以更类型安全的方式指向它:
char *p = &str[0][0]; // the same as "p = str[0];"
str[0]
指的是str
的第一个元素,即str[0]
类型是一个15char
的数组,然后您只需引用第一个char
并获取它的地址- &(str[0])[0]
,或者简单地使用带有“str[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"
然后
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"
这些操作很好,因为第二个参数的类型是正确的,而且我们知道字符串是以nul结尾的。
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]
初始化,因为它们有不兼容的类型:“指向三个int
的数组”和“四个int
/指向int
的数组”(感谢衰减)。而且n
也不能用num
初始化,因为它们也有不兼容的类型。根据我对你想要什么的猜测,你应该从下一个角度看:
int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*nm)[4] = num + 1;
int *n = &num[0][0];
最后一个是:
printf("n - %d\n",n[10]); // statement D
printf("nm - %d\n",nm[0][0]);
解除引用是正确的,传递的参数也是正确的,但请记住,指针初始化错误。
霍普,我已经回答了你所有的问题。
发布于 2016-07-27 22:42:50
您的分段错误是由于您将错误的类型传递给printf。
写入p[3]
时,您将延迟指向矩阵str
第一行的第4行的指针。与*(p+3)
相同
如果你想打印第三个字符,你应该
printf("%c\n",p[3]);
如果要打印第一个C-字符串(矩阵的第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-字符串为空终止,因此,例如,字符串"Pointer to"
将占用11
字符。
最后一件事是关于int
指针。它工作得很好,因为%d
格式说明符需要一个int
值,而不是地址。因此,写作:
printf("n - %d\n",n[10]);
完全正确,因为n[10]
正在取消引用num
矩阵的第11元素,即第3行的第3元素。与*(n+10)
相同
https://stackoverflow.com/questions/38628411
复制相似问题