为什么C的printf格式string同时具有%c和%s?
为什么C的printf格式string同时具有%c
和%s
?
我知道%c
代表一个单独的字符, %s
代表一个以空字符结尾的string,但是string表示本身是不够的?
可能要区分以空字符结尾的字符和字符。 如果他们只有%s
,那么每个单独的字符也必须以null结尾。
char c = 'a';
在上面的情况下, c
必须是空终止的。 这是我的假设,虽然:)
%s
打印字符,直到达到0
(或'\0'
,同样的事情)。
如果你只是有一个char x;
,用printf("%s", &x);
打印printf("%s", &x);
– 你必须提供地址,因为%s
期望char*
– 会产生意想不到的结果,因为&x + 1
可能不是0
。
所以你不能只打印一个单一的字符,除非它是空终止(非常无效)。
编辑:正如其他人已经指出的,两个期望VAR参数不同的事情 – 一个指针,另一个单一的字符。 但是那个区别有些清楚。
其他人提到的问题是,单个字符必须是空的而不是真实的。 这可以通过提供一个精确的格式%.1s
来处理。
我认为更重要的是,对于任何forms的%s
,你都必须提供一个指向一个或几个字符的指针。 这意味着你将无法打印右值(计算expression式,函数返回等)或寄存器variables。
编辑:我真的很生气的反应这个答案,所以我可能会删除这个,这是真的不值得。 似乎人们甚至没有读过这个问题,也没有知道如何去欣赏这个问题的技术性。
说清楚:我不是说你应该比%c
更喜欢%.1s
。 我只是说,为什么%c
不能被replace的原因是不同于其他答案假装告诉。 这些其他的答案在技术上是错误的。 空终止不是%s
的问题。
printf函数是一个可变参数函数,这意味着它具有可变数量的参数。 在调用函数(printf)之前,将参数压入堆栈。 为了使printf函数能够使用这个堆栈,它需要知道关于堆栈内容的信息,格式化string被用于这个目的。
例如
printf( "%c", ch ); tells the function the argument 'ch' is to be interpreted as a character and sizeof(char)
而
printf( "%s", s ); tells the function the argument 's' is a pointer to a null terminated string sizeof(char*)
printf函数内部不可能确定堆栈内容,例如区分'ch'和's',因为在C中在运行时没有types检查。
%s
说打印所有的字符,直到你find一个null(把这个variables作为一个指针)。
%c
表示只打印一个字符(把variables当作字符码)
使用%s
作为字符是行不通的,因为字符将被当作一个指针来对待,然后它将尝试打印所有位于内存中的字符,直到find一个null
从其他方面窃取答案以不同的方式解释。
如果你想使用%s
来打印一个字符,你可以使用下面的命令来正确的传递一个字符的地址,并且不要在屏幕上写垃圾,直到find一个null。
char c = 'c'; printf('%.1s', &c);
对于%s
,我们需要提供string的地址,而不是它的值。
对于%c
,我们提供了字符的值。
如果我们使用%s
而不是%c
,那么我们如何在字符后面提供'\0'
?
我喜欢给这个有趣的问题增加另一个观点。
真的,这涉及到数据input。 我已经在这里看到了答案,说明你可以提供一个指向char的指针,并提供一个
"%.1s"
这确实是事实。 但答案在于Cdevise人员试图为程序员提供灵活性,实际上是减less应用程序占用空间(尽pipe很小)的方法。
有时程序员可能会喜欢运行一系列if-else语句或switch-case语句,其中需要根据状态输出一个字符。 为此,对字符进行硬编码确实可以减less内存中的实际空间,因为单字符是8位而32位或64位(对于64位计算机)的指针。 指针将占用更多的内存空间。
如果你想通过使用实际的字符和指向字符的指针来减小大小,那么在printftypes的操作符中有两种方法可以这样做。 其中一个就是closures.1s,但是程序应该如何确定地知道你真的提供了一个chartypes的指针,而不是指向一个string(char数组)的指针呢? 这就是为什么他们跟“%c”一样,因为它是不同的。
有趣的问题:-)
C具有%c
和%s
格式说明符,因为它们处理不同的types。
一个char
和一个string和晚上和1差不多。
%c需要一个char,它是一个整型值 ,并根据编码规则打印它。
%s需要一个指向包含char值的内存位置的指针 ,并根据编码规则在该位置打印字符,直到find0(空)字符。
所以你们看到,在这两种情况下,这两种情况看起来是一样的,他们没有太多共同之处,因为一个人用价值观来工作,另一个用指针。 一种是将特定的整数值解释为ascii字符的指令,另一种是通过char迭代char的内存位置的内容,并解释它们,直到遇到一个零值。
由于没有人提供任何参考答案,所以这里是pubs.opengroup.com的printf规范,它与IBM的格式定义类似
%C
int参数应该被转换为一个无符号的字符,并且结果字节将被写入。
%S
参数应该是一个char数组的指针。 来自数组的字节应写入(但不包括)任何终止空字节。 如果指定了精度,则不应超过这么多字节。 如果未指定精度或大于数组的大小,则应用程序应确保数组包含空字节。
我用printf("%.1s", &c)
和printf("%c", c)
做了一个实验。 我用下面的代码来testing,而bash的time
效用得到了运行时间。
#include<stdio.h> int main(){ char c = 'a'; int i; for(i = 0; i < 40000000; i++){ //printf("%.1s", &c); get a result of 4.3s //printf("%c", c); get a result of 0.67s } return 0; }
结果表明使用%c
比%.1s
快10倍。 所以,尽pipe%s可以完成%c的工作,但仍然需要%c来提高性能。