void main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
}
输出结果为:
1631008309
5
编辑:谢谢。我看到'5'只有0x35,除了str [0] [4]我应该是。为什么我不能走出str [0] [4]而不是这个奇怪的1631008309?
天啊,我很愚蠢地问这个问题!谢谢大家,伙计。答案 0 :(得分:10)
你指向一个char **,它位于分配给你的二维数组的内存的开头。
当你向指针添加1时,它会向你移动指向的类型的大小,在这种情况下是char *的大小,在你的系统中显然是4个字节。然后你取消引用它并将结果视为int(%d),它给你我在评论中提到的a765来展开。当您取消引用它并将其视为char时,您正确得到5。
[我看到unwind已经删除了他们的答案,所以为了完整性我会补充说“a765”是你得到的更大数字的ASCII解释(0x61373635)。]
答案 1 :(得分:5)
这一行:
char** p = str;
毫无意义。 str
是包含7个字符的2个数组的数组。在表达式上下文中使用时,它会计算指向其第一个元素的指针,相当于:
&str[0]
其类型为“指向7个字符数组的指针”。这是没有办法类似于“指向char的指针”,这是p
的类型。其中任何一个都有意义:
char *p = str[0];
char *p = str[1];
char (*p)[7] = str;
答案 2 :(得分:5)
使用%d不会将字母数字的ASCII字符串转换为数字。使用%d意味着它期望找到的值将被解释为数字的二进制表示,并转换为TO ASCII以进行打印。
答案 3 :(得分:3)
请注意,C标准定义main()
程序返回int
,而不是void
。
鉴于代码:
#include <stdio.h>
int main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
return(0);
}
使用gcc -o x -Wall x.c
编译时,会收到警告:
x.c: In function ‘main’:
x.c:5: warning: initialization from incompatible pointer type
x.c:6: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘char *’
x.c:7: warning: format ‘%c’ expects type ‘int’, but argument 2 has type ‘char *’
(如果省略-Wall
,则不会收到格式警告。)
这告诉您正在向printf()
传递指针。打印指针并不是那么有用。但是,之前的警告还告诉您错误初始化变量p
。但是,最终结果是p
指向str
中空格的开头。当你打印
一个有趣的小怪癖:通常,诸如“1234567”的字符串包括终止NUL '\0'
;在你的arays中,因为你指定数组的长度是7而不是8,所以缺少终止null。小心你如何打印字符串!
以下是代码的另一种变体:
#include <stdio.h>
int main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
printf("%p %p %p -- %p %p %p\n", str, &str[0], &str[0][0], p, p+1, *(p+1));
printf("%.4s\n", (p+1));
return(0);
}
这给了我以下输出(来自Mac):
1631008309
5
0xbffffa5e 0xbffffa5e 0xbffffa5e -- 0xbffffa5e 0xbffffa62 0x61373635
567a
注意,地址str,&amp; str [0]和&amp; str [0] [0]都具有相同的值,并且p+1
进一步是四个字节。当被视为字符串时,它会打印第一个初始化程序的最后三个字节和第二个字节的第一个字节。
另外,为了好玩,使用gcc -m64 -o x64 x.c
编译,输出为:
1701077858
b
0x7fff5fbff9e0 0x7fff5fbff9e0 0x7fff5fbff9e0 -- 0x7fff5fbff9e0 0x7fff5fbff9e8 0x676665646362
bcde
答案 4 :(得分:1)
我理解你的困惑,这两个陈述是完全一样的。
两个语句都将*(p + 1)转换为指向解除引用之前的整数的指针,默认情况下是将所有内容转换为va_arg参数中的整数。
printf然后在第二个printf语句中打印它之前将整数截断为char。
此代码段更清晰地说明了发生了什么:
void main()
{
char str[2][7] = {"1234567", "abcdefg"};
char** p = str;
printf("%d\n", *(p+1));
printf("%c\n", *(p+1));
int n = *(p+1);
char c = *(p+1);
printf("0x%08X\n", n);
printf("0x%08X\n", c);
}
哪个输出:
1631008309
5
0x61373635
0x00000035
stdarg中的类型安全性在此解释:stdarg