假设我有两个功能:
void function1(int *ptr) {
printf("%d", *ptr);
}
和
void function2(char *str) {
printf("%s", str);
}
为什么 function2 工作,当之前没有尊重运算符时str
?str
那里只有它指向的地址,而不是我想的值。
假设我有两个功能:
void function1(int *ptr) {
printf("%d", *ptr);
}
和
void function2(char *str) {
printf("%s", str);
}
为什么 function2 工作,当之前没有尊重运算符时str
?str
那里只有它指向的地址,而不是我想的值。
当 str 之前没有遵循运算符时,为什么 function2 起作用
因为%s
,按照标准的定义,需要一个char *
,即一个地址。
7.21.6.1
如果不存在 l 长度修饰符,则参数应为指向字符类型数组的初始元素的指针。数组中的字符被写入(但不包括)终止空字符。如果指定了精度,则写入的字节数不会超过这个数。如果未指定精度或大于数组的大小,则数组应包含空字符。
因为 apointer to a char
在使用时是特殊的printf
。它不是将其视为指向单个字符的指针,而是将其视为指向NUL
分隔字符数组中第一个元素的指针,打印一个字符串而不是一个指针。
您在 C 中引用字符串的方式是通过其第一个字符的地址。读取字符串的函数将读取该地址处的字节,对其进行处理(例如打印它,在 的情况下printf()
),然后移动到下一个字符。这一直持续到找到零字节,表示字符串的结尾。
这基本上是一种节省内存的方法。其他基本数据类型,如int
,足够小,可以廉价地复制它们的值,因此无需引用对象的地址。
因为当我们写
char *s="hello";
s
默认情况下,采用第一个元素的第一个地址的地址,即 printf 中的“h”地址和 %s 打印整个字符串而不是元素@第一个位置。因此,它从不需要遵从运算符。是否打印第一个元素或所有元素可能会使 C 编译器感到困惑。
这样做的原因是因为该printf()
函数已被编写为理解传递给它的不同类型的参数。字符串中的格式说明符告诉printf()
每个参数应该是什么。然后文档会告诉您要传递给它的内容。
IE。基本上它可以工作,因为printf()
遵循定义的规范,并且您正在遵循它。
因此,在您的第一个示例中,您使用 %d 格式。 printf()
这意味着参数应该是一个整数值。不是指向整数的指针,而是整数。这就是为什么这有效:
void function1(int *ptr) {
printf("%d", *ptr);
}
这不会:
void function1(int *ptr) {
printf("%d", ptr);
}
你的第二个例子是一个字符串,这里有一些混淆的可能性,因为 C 中的字符串并不是真正的直接数据类型(因此)。 它们是指向一个字符的指针,该字符后跟其他字符,然后以 NULL \0 终止。
void function2(char *str) {
printf("%s", str);
}
现在,如果字符串是 C 中的一种数据类型,那么您可能会以与处理其他值相同的方式传递它们(这纯粹是假设):
void function2(string str) {
printf("%s", str);
}
总而言之:
%d -> int
%s -> char *