为什么C的printf格式字符串同时具有%c
和%s
?
我知道它%c
代表一个字符并%s
代表一个以空值结尾的字符串,但是仅字符串表示就够了吗?
为什么C的printf格式字符串同时具有%c
和%s
?
我知道它%c
代表一个字符并%s
代表一个以空值结尾的字符串,但是仅字符串表示就够了吗?
%c
需要一个char
类型的数据-一个值原语。%s
需要一个数据char *
类型的指针。尽管它们都适用于文本,但两者之间的差异在C中是巨大的。
Answers:
可能区分以null结尾的字符串和字符。如果他们只有%s
,那么每个字符都必须以null结尾。
char c = 'a';
在上述情况下,c
必须以null终止。虽然这是我的假设:)
%.1s
%s
必须为null终止。如果没有%c
该语言,那么在我上面的示例中,标识符c
必须以null终止,以便能够与格式说明符一起使用%s
。
printf("%s", c)
不起作用,不是因为终止为空,而是因为printf
期望%s
指向一个内存位置,而c
is是一个字符值。空终止是printf("%s", &c)
不起作用的原因,但是即使这样,具有%c
标识符仍然有意义,因为要求&c
与其他所有变量类型的打印方式不一致。因此,仅说“这是因为终止终止”是不正确的。
char*
来获得要打印的一个字符%s
。只是重申BlueRaja所说的-Juan
%s
打印出字符,直到到达一个0
(或'\0'
相同的东西)为止。
如果只有a char x;
,则用printf("%s", &x);
-进行打印(您必须提供地址,因为%s
期望achar*
)会产生意想不到的结果,而&x + 1
可能不会0
。
因此,您不能只打印单个字符,除非该字符以空字符结尾(非常无效)。
编辑:正如其他人指出的,两者在var args参数中期望不同的东西-一个是指针,另一个是单个char。但是这种区别是显而易见的。
%s
带指针而%c
带字符本身。
其他人提到的一个字符必须以null结尾的问题并不是一个真正的问题。这可以通过提供一种精确的格式来解决%.1s
。
我认为更重要的是,对于%s
任何形式的内容,您都必须提供一个或多个字符的指针。这意味着您将无法打印右值(计算表达式,函数返回等)或注册变量。
编辑:我对这个答案的反应真的很生气,所以我可能会删除它,这确实不值得。似乎人们对此做出了反应,甚至没有阅读问题或不知道如何理解问题的技术性。
明确说明:我并不是说您应该优先%.1s
于%c
。我只说%c
不能用其他理由代替的理由与其他答案不同。这些其他答案在技术上只是错误的。空终止不是的问题%s
。
%.1s
将具有仅打印一个甚至都不为null终止的字符的功能,因此null终止不是对“ introduce”的有效反对%c
。
%.1s
期待achar
或achar*
吗?
%.1s
该字符来打印字符。这不是问题。问题是是否%c
严格必要。我对此表示肯定的回答,只是说说原因与其他答案中给出的原因不同。
printf函数是可变参数函数,这意味着它具有可变数量的参数。在调用函数(printf)之前,将参数压入堆栈。为了使函数printf使用堆栈,它需要知道有关堆栈中内容的信息,为此使用了格式字符串。
例如
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中,运行时不进行类型检查。
sizeof
规格完全错误。首先,ch
被提升为int
(或在某些平台上为unsigned
)并将其printf
解释int
为字符。因此,“在堆栈上”该参数的大小为sizeof(int)
。第二秒钟你又错了,没错sizeof(char*)
。sizeof(int)
可以(现在经常)与此不同。第三,没有必要涉及“堆栈”之类的东西。这些参数的传递方式由平台ABI自行决定,一切都可能在寄存器中发生。
%s
说打印所有字符,直到找到空(将变量作为指针处理)。
%c
说只打印一个字符(将变量作为字符代码处理)
使用%s
的字符不工作,因为性格会像一个指针来处理,那么它会尝试打印以下所有内存中发生的字符,直到它找到一个空
偷走其他答案,以不同的方式进行解释。
如果您想使用来打印字符%s
,则可以使用以下代码正确地将其传递给char地址,并防止其在屏幕上写入垃圾,直到找到空值为止。
char c = 'c';
printf('%.1s', &c);
'\0'
和空指针都在内部表示为0
:)
0
。它们的内部表示形式可以完全不同。空字符通常为8位,而空指针通常为32或64位。此外,一个空指针的内部表示并不一定是所有位归零(虽然它很常用的)。
if (pointer)
或if (pointer != 0 )
或if(pointer != NULL )
另外,我认为使用8、16、32位的0差别不大。bytes.com/topic/c/answers/213647-null-c
我想为这个有趣的问题添加另一个观点。
确实,这归结于数据类型。我在这里看到的答案是,您可以提供一个指向char的指针,并提供一个
"%.1s"
的确是这样。但是答案在于C设计人员试图为程序员提供灵活性,并且确实是(虽然很小)减少应用程序占用空间的方法。
有时,程序员可能希望运行一系列if-else语句或切换用例,其中需要根据状态简单地输出字符。为此,硬编码字符确实可以占用较少的实际内存空间,因为单个字符为8位,而指针为32或64位(对于64位计算机)。指针将占用更多的内存空间。
如果您想通过使用实际的char与指向char的指针来减小大小,则可以在printf类型的运算符中采用两种方法来做到这一点。一种方法是从.1开始,但是例程应该如何确定您确实在提供一个char类型与一个char指针或一个字符串(char数组)的指针呢?这就是为什么他们使用“%c”的原因,因为它有所不同。
好玩的问题:-)
C具有%c
和%s
格式说明符,因为它们处理不同的类型。
Achar
和一个字符串与Night和1差不多一样。
scanf(%s, &ch)
andscanf(%c, &ch)
语句返回相同的结果。考虑到ch是一个类似char的字符char ch
;
我已经用printf("%.1s", &c)
和进行了实验printf("%c", c)
。我使用下面的代码进行测试,并使用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
速度是的10倍%.1s
。因此,尽管%s可以完成%c的工作,但仍需要%c来提高性能。
由于没有人提供任何参考答案,因此这是pubs.opengroup.com的printf规范,它与IBM的格式定义相似。
%C
将int参数转换为无符号字符,并写入结果字节。
%s
该参数应为指向char数组的指针。数组中的字节应写入(但不包括)任何终止的空字节。如果指定了精度,则最多只能写入多个字节。如果未指定精度或大于数组的大小,则应用程序应确保数组包含一个空字节。
%s
,那么每个字符都必须以null结尾。char c ='a'; ,在这种情况下c
必须以null结尾。不过,这是我的假设:)