我们有以下代码片段:
char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
printf("%s\n", tab);
我不明白为什么我们在调用我得到警告但没有错误,程序运行精细。它会打印“printf
时没有收到错误/警告。12
”
printf
期望类型为char *
的参数,即指向char
的指针。因此,如果我声明char arr[3]
,则arr
是包含char
的内存单元的地址,因此如果我用它调用printf
,它将衰减到指向char 的指针,即char *
类似地,tab
是包含char
,因此{{1}将衰减到tab
,这应该是一个问题,因为char **
期待printf
。
有人可以解释这个问题吗?
我得到的警告是:
char *
答案 0 :(得分: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: In function ‘main’: test.c:5: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[3]’
指针是指针
%s
的{{1}}参数向函数指示它将接收指针(到字符串)。 C中的字符串只是由ASCII-Z终止的一系列字节。 printf
变量是一个指针。一些编译器会发出有关指针不匹配的警告。但是,代码仍应打印出tab[2][3]
,因为12
的代码遍历内存,从指定的内容开始(打印字符),直到找到零字节为止。 1,2,和0在内存中连续设置,从printf
变量表示的地址开始。
<强>实验强>
作为一项实验,编译并运行以下代码时会发生什么:
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
?
答案 1 :(得分:4)
tab参数与printf()调用中的省略号匹配。 C和C ++编译器没有义务检查这些参数。
答案 2 :(得分:4)
您认为tab
会衰变为char **
是错误的:tab
类型为char [2][3]
,即它会衰减为char (*) [3]
。重要的是要理解尽管数组和指针通常表现相似,但它们并不是一回事。 printf()
需要char *
,因此需要char (*) [3]
的位并相应地解释它们。虽然它适用于您的平台,但C标准并不能保证这一点:两个指针都引用相同的内存位置,但它们的表示形式不一定相同。
检查my answer至this related question了解详情。
答案 3 :(得分:1)
你似乎已经自己解释了,我看不出还有什么要说的。
tab
是一个包含两个char *
的数组。 tab
的每个元素都是printf
可以接受的字符串,但tab
本身是不可接受的,因为它是指向char的指针。