printf(“...%c ...”,“\ 0”)和家人 - 会发生什么?

时间:2010-05-10 15:48:39

标签: c++ c string format printf

在遇到%c格式的\0 / NULL给定值时,采用printf格式字符串的各种函数如何表现? 他们应该怎么做?安全吗?它定义了吗?它是特定于编译器的吗?

e.g。 sprintf() - 它会将结果字符串裁剪为NULL吗?它会返回多长时间?

printf()会输出整个格式字符串还是只输出新的NULL?

va_args + vsprintf / vprintf会以某种方式受到影响吗?如果是这样,怎么样?

如果我这样做,我是否会冒内存泄漏或其他问题的风险?在std :: string.c_str()?

中的某个点处拍摄此NULL

避免这种警告的最佳方法是什么(消毒输入?)

3 个答案:

答案 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)。