Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C程序如何生成这样的输出?_C_Pointers - Fatal编程技术网

C程序如何生成这样的输出?

C程序如何生成这样的输出?,c,pointers,C,Pointers,输出为: void main() { char str[2][7] = {"1234567", "abcdefg"}; char** p = str; printf("%d\n", *(p+1)); printf("%c\n", *(p+1)); } 1631008309 5 0xbffffa5e 0xbffffa5e 0xbffffa5e -- 0xbffffa5e 0xbffffa62 0x61373635 567a 编辑:谢谢。我看到“5”仅为0x35,

输出为:

void main()
{
    char str[2][7] = {"1234567", "abcdefg"};
    char** p = str;
    printf("%d\n", *(p+1));
    printf("%c\n", *(p+1));
}
1631008309
5
0xbffffa5e 0xbffffa5e 0xbffffa5e -- 0xbffffa5e 0xbffffa62 0x61373635
567a
编辑:谢谢。我看到“5”仅为0x35,而不是我认为的str[0][4]。为什么我不能用str[0][4]代替这个奇怪的1631008309

天哪,我真傻,竟然问这个问题!谢谢大家。

这句话:

1631008309
5
毫无意义
str
是一个由2个数组和7个字符组成的数组。在表达式上下文中使用时,其计算结果为指向其第一个元素的指针,相当于:

char** p = str;
其类型为“指向7个字符数组的指针”。这与“
p
类型的“指向char的指针”类似。以下任何一项都是有意义的:

&str[0]

使用%d不会将字母数字的ASCII字符串转换为数字。使用%d意味着它希望找到的值将被解释为数字的二进制表示形式,并转换为ASCII进行打印。

您正在将一个字符**指向分配给二维数组的内存的开头

当您将1添加到指针时,它会按所指向类型的大小移动您,在本例中为char*的大小,这在您的系统中显然是4个字节。然后,您将取消引用它,并将结果作为int(%d)处理,这将为您提供我在评论中提到的a765,以便展开。当您取消引用它并将其视为一个字符时,您正确地得到了5


[我看到unwind删除了他们的答案,因此为了完整起见,我将添加“a765”是对您得到的较大数字(0x61373635)的ASCII解释。]

我理解您的困惑,这两种说法完全相同

这两个语句都将*(p+1)转换为指向整数的指针。在取消引用之前,默认情况下,将所有内容转换为va_arg参数中的整数

printf然后在第二个printf语句中打印前将整数截断为字符

此代码片段更清楚地说明了发生了什么:

char *p = str[0];

char *p = str[1];

char (*p)[7] = str;
哪些产出:

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);
}

stdarg中的类型安全在这里解释:

注意,C标准定义
main()
程序返回
int
,而不是
void

鉴于代码:

1631008309
5
0x61373635
0x00000035
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”
;在Aray中,由于指定数组的长度为7而不是8,因此缺少终止null。打印字符串时要小心

下面是代码的另一个变体:

1631008309
5
0x61373635
0x00000035
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 *’
请注意,地址str、&str[0]和&str[0][0]都有相同的值,
p+1
是四个字节。当作为字符串处理时,它将打印第一个初始值设定项的最后三个字节和第二个初始值设定项的第一个字节

此外,为了好玩,使用
gcc-m64-o x64 x.c
编译,输出为:

void main()
{
    char str[2][7] = {"1234567", "abcdefg"};
    char** p = str;
    printf("%d\n", *(p+1));
    printf("%c\n", *(p+1));
}
1631008309
5
0xbffffa5e 0xbffffa5e 0xbffffa5e -- 0xbffffa5e 0xbffffa62 0x61373635
567a

你期待什么呢?1631008309==0x61373635;0x61 0x37 0x36 0x35='a'7'6'5'当然是!我从来没有这样想过。因为
str+1
*(str+1)
是相同的值,所以我犹豫了。嘿,你能解释一下这里发生了什么吗?1631008309==0x61373635是怎么回事?5==0x35是怎么回事?是的,我想我读到的是“为什么程序生成这个输出而不是我期望的输出”。