在遇到%c
格式的\0
/ NULL
给定值时,采用printf格式字符串的各种函数如何表现?
他们应该怎么做?安全吗?它定义了吗?它是特定于编译器的吗?
e.g。 sprintf()
- 它会将结果字符串裁剪为NULL吗?它会返回多长时间?
printf()
会输出整个格式字符串还是只输出新的NULL?
va_args
+ vsprintf
/ vprintf
会以某种方式受到影响吗?如果是这样,怎么样?
如果我这样做,我是否会冒内存泄漏或其他问题的风险?在std :: string.c_str()?
中的某个点处拍摄此NULL避免这种警告的最佳方法是什么(消毒输入?)
答案 0 :(得分:8)
任何采用标准C字符串的函数都将在第一个null处停止,无论它是如何到达的。
当您在格式中使用%c并使用0作为字符值时,它会在输出中插入null。 printf
将输出null作为输出的一部分。 sprintf
也会将null插入到结果字符串中,但是当您将输出传递给另一个函数时,该字符串将在该点结束。
std :: string很乐意在其内容的任何地方包含null,但是当你使用c_str方法将它传递给函数时,请参阅上面的答案。
答案 1 :(得分:3)
输出NUL时会发生什么情况取决于输出设备。
这是一个非打印字符,即isprint('\0') == 0
;所以当输出到显示设备时,它没有明显的影响。如果重定向到文件(或调用fprintf()
),它将在文件中插入NUL(零字节);其含义取决于文件的使用方式。
当输出到C字符串时,它将被标准字符串处理函数解释为字符串终止符,尽管任何其他后续格式说明符仍然会导致数据在NUL之后放入缓冲区,这对标准是不可见的字符串处理功能。如果最终不将数组解释为C字符串,这可能仍然有用。
如果我这样做,我是否会冒内存泄漏或其他问题的风险?在std :: string.c_str()?
中的某个点处拍摄此NULL
完全不清楚你的意思,但是如果你建议使用std::string.c_str()
返回的指针作为sprintf()
的缓冲区;别! c_str()
返回const char*
,通过这样的指针修改字符串是未定义的。然而,这是一个不同的问题,并不完全与将NUL插入字符串有关。
避免这种警告的最佳方法是什么(消毒输入?)
我正在努力想到你可以“意外”编写这样的代码的情况,那么为什么你需要防范它呢?你有特定的情况吗?尽管我发现它难以置信,而且可能是不必要的,但是很难:
if( c != 0 )
{
printf( "%c", c ) ;
}
或者可能更有用(因为在输出中你可能想要避免使用其他字符)
if( isgraph(c) || isspace(c) )
{
printf( "%c", c ) ;
}
将仅输出可见字符和空格(空格'\t'
,'\f'
,'\v'
,'\n'
,'\r'
)。
请注意,您可能还会考虑isprint()
而不是isgraph(c) || isspace(c)
,但不包括'\t'
,'\f'
,'\v'
,'\n'
和{ {1}}
答案 2 :(得分:3)
printf()
和sprintf()
将继续使用'\0'
插入的%c
个字符,因为它们的输出是根据格式字符串的内容定义的,%c
1}}不表示格式字符串的结尾。
这包括他们的数量;因此:
sprintf(x, "A%cB", '\0')
必须始终返回3(虽然strlen(x)
之后会返回1)。