4

我们有以下代码片段:

char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
printf("%s\n", tab);

而且我不明白为什么我们在调用printf. 我确实收到警告但没有错误,并且程序运行正常。它打印' 12'。
printf期待一个类型的参数char *,即指向 的指针char。因此,如果我声明char arr[3], thenarr是包含 a 的内存单元的地址char,所以如果我用它调用printf它,它将衰减为指向 char的指针,即char *
类似地,tab内存单元的地址包含3 个字符的类型数组,而内存单元的地址包含char,因此tab将衰减到char **,这应该是一个问题,因为printf期望char *.

有人可以解释这个问题吗?

附录:

我得到的警告是:
a.c:6: warning: char format, different type arg (arg 2)

4

4 回答 4

6

示例源

#include <stdio.h>

int main( void ) {
  char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
  printf("%s\n", tab);

  return 0;
}

编译警告

$ gcc test.c
test.c:在函数'main'中:
test.c:5:警告:格式“%s”需要类型“char *”,但参数 2 的类型为“char (*)[3]”</pre>

指针就是指针

to的%s参数向printf函数表明它将接收一个指针(指向一个字符串)。在 C 中,字符串只是一系列以 ASCII-Z 结尾的字节。tab[2][3]变量是一个指针。一些编译器会发出关于指针不匹配的警告。但是,代码仍应打印出来,12因为printf' 的代码从给定的指针开始遍历内存(随行打印字符),直到找到零字节。1、2 和 \0 在内存中连续设置,从tab变量表示的地址开始。

实验

作为一个实验,当您编译并运行以下代码时会发生什么:

#include <stdio.h>

int main( void ) {
  char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
  printf("%s\n", tab[1]);

  return 0;
}

不要害怕尝试。看看你能不能根据你现在所知道的得出答案。您现在如何参考tab(根据实验)以摆脱警告并仍然显示12

于 2009-06-29T08:26:19.040 回答
4

tab 参数匹配 printf() 调用中的省略号。C 和 C++ 编译器没有义务检查这些参数。

于 2009-06-29T08:28:22.700 回答
4

tab您将衰减到的假设char **是错误的:tab有 type char [2][3],即它将衰减到char (*) [3]。重要的是要理解,尽管数组和指针的行为通常相似,但它们并不是一回事。printf()期望 a char *,因此它需要 the 的位char (*) [3]并相应地解释它们。尽管它适用于您的平台,但 C 标准并不保证这一点:两个指针都引用相同的内存位置,但它们的表示不必相同。

有关详细信息,请查看对此相关问题的回答。

于 2009-06-29T09:02:04.803 回答
1

你好像已经解释过了,我不明白还有什么要说的。

tab是两个的数组char *。的每个元素都是一个可以接受tab的字符串,但它本身是不可接受的,因为它是一个指向 char 的指针。printftab

于 2009-06-29T08:24:36.297 回答