在我所知,%c
期望int值(如char
在Ç视为整数),%s
预计char *
作为参数,但我的疑问是,请问%S需要一个指向字符的块?它可以指向双引号中的单个字符吗?%s和%c格式说明符之间有什么区别?
例如:
char * s = "string";
printf("%s",s);// output: string
如何能够计算出所述存储器块,其中该字符串存在并通过'\0'
终止编译器?。
在我所知,%c
期望int值(如char
在Ç视为整数),%s
预计char *
作为参数,但我的疑问是,请问%S需要一个指向字符的块?它可以指向双引号中的单个字符吗?%s和%c格式说明符之间有什么区别?
例如:
char * s = "string";
printf("%s",s);// output: string
如何能够计算出所述存储器块,其中该字符串存在并通过'\0'
终止编译器?。
编译器如何能够找出 字符串以'\ 0'结尾的内存块?
因为字符串文字(双引号之间的x个字符数量)获取编译器向其添加的NUL终止符\0
。
char * s = "string";
char foo = s[6]; // \0
所以printf
只是打印字符串中的字符,直到找到一个\0
。
是%s需要指向字符块的指针。它可以指向一个 单引号双引号?
是的你可以,双引号中的单个字符仍然是一个字符串文字,最后是\0
。
在双引号的单个字符仍然是一个C字符串,实际上包含两个字符:单字符加上终止空字符:
char const* str = "a"; // actually points to an array { 'a', '\0' }
所以你还是有%s
使用它。其实,你可以与%c
使用它,也一样,如果你取消引用字符串:
printf("%c\n", *str);
// ^
你可以做到这一点与任何C-字符串(与空单“”的除外),但只有前然后字符将被印...
加成响应您的评论:
函数调用(至少的cdecl和stdcall调用约定)将函数参数压入堆栈完成(在大多数现代系统,类型比int小的int在堆栈中被提升为int)。 printf
然后简单地分析格式字符串,如果它发现%s,它会将堆栈中的下一个sizeof(void*)
字节解释为指向空终止字符串的指针(因此直接通过str
),如果它发现%c,它将直接读取字符从堆栈 - 所以你需要放置一个,而不是一个指针,因此你需要解除引用。
或者,您可以使用'str [0]'而不是'* str'。 –
@Aconcagua为什么%c需要尊重str,但%s不是? –
@ Matec009添加了一些额外的信息给我的答案。 – Aconcagua
字符串由字符组成,就像char数组由字符组成一样。
编译器应该聪明,和gcc必须能够识别哪个是哪个函数,[执行相应的操作(如添加一个空结束)
并回答你的问题,是的,它仍然会打印到控制台,就像
char * s = "string";
printf("%s",s);// output: string
将打印到控制台。
是的,它可以指向长度为1的字符串。 –
*双*引号中的单个字符仍然是一个C字符串,即NUL结尾,与单引号内的单个字符不同。 – Evert