我正在学习C
,我想使用函数打印一个名字,所以我做了这个代码:
#include <stdio.h>
void pn(char x);
void main()
{
pn("HHH");
}
void pn(char x)
{
printf("Hello %sn",x);
}
并且输出什么都没有,所以我更改参数并将其作为指针,然后它就可以工作了:
void pn(char* x);
void main()
{
pn("HHH");
}
void pn(char* x)
{
printf("Hello %sn",x);
}
输出是:你好HHH
据我所知,指针是存储变量的地址,但这里我不发送任何地址? 那么为什么只有当我把指针作为参数时它才有效呢?
在第一个程序中,函数参数
void pn(char x);
具有类型char
,即函数期望作为参数的单个字符。
但是,该函数以字符串文字"HHH"
作为其参数调用
pn("HHH");
C 中的字符串文本具有字符数组的类型。例如,字符串文本"HHH"
的类型为char[4]
,因为字符串文本还包括一个不可见的终止零字符。
例如,在表达式中使用,例如作为函数参数,数组被隐式转换为指向其第一个元素的指针。因此,字符串文本"HHH"
被转换为指向第一个字符'H'
的char *
类型的临时对象。
因此,由于参数和相应参数不兼容,函数具有未定义的行为。
在第二个程序中,函数参数被正确地更改为类型char *
并且程序产生了预期的结果。
如果你想在第一个程序中只输出一个字符,那么至少应该按以下方式更改它
#include <stdio.h>
void pn(char x);
void main()
{
pn("HHH"[0]);
}
void pn(char x)
{
printf("Hello %cn",x);
}
或者调用函数会更清楚,例如
pn( 'H' );
传递字符文本。
C 中的字符串定义为以空字符结尾的字符数组。 C 中的数组由指向数组中第一个元素的指针定义。
您的函数不起作用,因为它的参数只接受单个字符作为参数,而不是指向字符数组的指针。
">那么为什么只有当我把指针作为参数时它才有效?
"HHH"
是 4char
(char [4]
( 数组类型的字符串文字。
当您在 C 中使用字符串文字作为函数参数时,字符串文字将被计算为指向构成字符串的char
数组的第一个元素的指针,键入指向char
(char *
的指针(。
在这种情况下,"HHH"
将获得一个指向包含第一个H
的第一个char
元素的内存地址的指针。
如果您现在使用x
作为类型char
的参数,则有:
-
调用函数时的类型不匹配
pn
参数和参数 -char *
与char
,它调用未定义的行为,以及 -
此外,
printf("Hello %sn",x);
处的类型不匹配,因为%s
转换说明符需要指向 char 的类型指针的参数。这也调用了未定义的行为,因为您提供了类型char
的参数,根据 C 标准,这是不允许的。"如果转换规范无效,则行为未定义。288(如果任何参数不是相应转换规范的正确类型,则行为是未定义的。
"288(请参阅"未来的图书馆方向"(7.31.11(。
来源:C18,7.21.6.1/9 - "fprintf 函数">
旁注:
-
通常,编译器应默认警告您这两种类型不匹配(没有任何其他标志(。因此,您似乎要么忽略编译器警告,要么没有合适的编译器。将编译器切换到
GCC
或Clang
(如果尚未完成(,并且永远不要忽略编译器警告:为什么我应该始终启用编译器警告?