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

发布于 2024-09-01 11:58:59 字数 441 浏览 6 评论 0原文

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

例如 sprintf() - 它会在 NULL 处裁剪结果字符串吗?返回的长度是多少?

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

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

如果我在 std::string.c_str() 中的某个点拍摄这个 NULL,我是否会面临内存泄漏或其他问题的风险?

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

How will various functions that take printf format string behave upon encountering the %c format given value of \0/NULL?
How should they behave? Is it safe? Is it defined? Is it compiler-specific?

e.g. sprintf() - will it crop the result string at the NULL? What length will it return?

Will printf() output the whole format string or just up to the new NULL?

Will va_args + vsprintf/vprintf be affected somehow? If so, how?

Do I risk memory leaks or other problems if I e.g. shoot this NULL at a point in std::string.c_str()?

What are the best ways to avoid this caveat (sanitize input?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

桃扇骨 2024-09-08 11:58:59

任何采用标准 C 字符串的函数都会在第一个 null 处停止,无论它是如何到达那里的。

当您在格式中使用 %c 并使用 0 作为字符值时,它将在输出中插入 null。 printf 将输出 null 作为输出的一部分。 sprintf 还会将 null 插入到结果字符串中,但当您将输出传递给另一个函数时,该字符串似乎在该点结束。

std::string 很乐意在其内容中的任何位置包含 null,但是当您采用 c_str 方法将其传递给函数时,请参阅上面的答案。

Any function that takes a standard C string will stop at the first null, no matter how it got there.

When you use the %c in a format and use 0 for the character value, it will insert a null into the output. printf will output the null as part of the output. sprintf will also insert the null into the result string, but the string will appear to end at that point when you pass the output to another function.

A std::string will happily contain a null anywhere within its contents, but when you take the c_str method to pass it to a function see the above answer.

薄荷梦 2024-09-08 11:58:59

输出 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''\r'

What happens when you output a NUL depends on the output device.

It is a non printing character, i.e. isprint('\0') == 0; so when output to a display device, it has no visible affect. If redirected to a file however (or if calling fprintf()), it will insert a NUL (zero byte) into the file; the meaning of that will depend on how the file is used.

When output to a C string, it will be interpreted as a string terminator by standard string handling functions, although any other subsequent format specifiers will still result in data being placed in the buffer after the NUL, which will be invisible to standard string handling functions. This may still be useful if ultimately the array is not to be interpreted as a C string.

Do I risk memory leaks or other problems if I e.g. shoot this NULL at a point in std::string.c_str()?

It is entirely unclear what you mean by that, but if you are suggesting using the pointer returned by std::string.c_str() as the buffer for sprintf(); don't! c_str() returns a const char*, modifying the string through such a pointer is undefined. That however is a different problem, and not at all related to inserting a NUL into a string.

What are the best ways to avoid this caveat (sanitize input?)

I am struggling to think of a circumstance where you could "accidentally" write such code, so why would you need to guard against it!? Do you have a particular circumstance in mind? Even though I find it implausible, and probably unnecessary, what is so hard about:

if( c != 0 )
{
    printf( "%c", c ) ;
}

or perhaps more usefully (since there are other characters you might want to avoid in the output)

if( isgraph(c) || isspace(c) )
{
    printf( "%c", c ) ;
}

which will output only visible characters and whitespace (space, '\t','\f','\v','\n','\r').

Note that you might also consider isprint() rather than isgraph(c) || isspace(c), but that excludes '\t','\f','\v','\n' and '\r'

顾冷 2024-09-08 11:58:59

printf()sprintf() 将继续经过用 %c 插入的 '\0' 字符,因为它们的输出是根据格式字符串的内容定义的,并且 %c 并不表示格式字符串的结尾。

这包括他们的数量;因此:

sprintf(x, "A%cB", '\0')

必须始终返回 3(尽管之后 strlen(x) 将返回 1)。

printf() and sprintf() will continue past a '\0' character inserted with %c, because their output is defined in terms of the content of the format string, and %c does not denote the end of the format string.

This includes their count; thus:

sprintf(x, "A%cB", '\0')

must always return 3 (although strlen(x) afterwards would return 1).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文