printf()的字符串宽度是否安全,没有未终止的字符串?

YSC*_*YSC 4 c printf undefined-behavior language-lawyer

以下是否定义明确?

const char not_a_c_string[] = { 'h', 'e', 'l', 'l', 'o' };
printf( "%.5s", (const char*) not_a_c_string );
Run Code Online (Sandbox Code Playgroud)

这是关于具体形式的问题"%.5s",而不是如何打印可能不是NUL终止的字符串?因为这个问题已在这里得到解答,其中"%.*s"提出了构造.

Sou*_*osh 11

首先,我相信,你的意思是询问精度,而不是场宽.所以,你的例子是看起来像

 printf( "%.5s", (const char*) not_a_c_string );  //precision
Run Code Online (Sandbox Code Playgroud)

代替

 printf( "%5s", (const char*) not_a_c_string );   //field width.
Run Code Online (Sandbox Code Playgroud)

考虑到上面的方法,不,在你的例子中它不会是UB.

引述C11标准,章§7.21.6.1,fprintf功能,第8段(重点煤矿)

s               如果不存在l长度修饰符,则参数应为指向字符类型数组的初始元素的指针.(280)来自数组的字符被写入(但不包括)终止空字符.如果指定了精度,则不会写入多少个字节.如果未指定精度或大于数组的大小,则数组应包含空字符.

因此,只有在您使用时才需要使用空分隔数组(字符串)

  • 缺少精度
  • 提供的精度是>提供的char数组的大小.

在您的情况下,提到的精度(5)不大于数组的大小(也是5).所以,没关系.


FWIW,如果例子仍然存在

 printf( "%5s", (const char*) not_a_c_string );
Run Code Online (Sandbox Code Playgroud)

然后它将是UB,因为你将缺少那里的精度.

  • @PaulR:我想你错过了第一句话:"不,在你的例子中,它不会**成为UB." (强调我的)他同意你的意见 (2认同)