英文:
Does snprintf clobber the buffer after null-terminator?
问题
snprintf
函数将'h'
、'i'
和'\0'
写入buffer
。根据标准,snprintf
不会触及buffer[3]
和buffer[4]
的内容。在Visual Studio 2019中,未使用的缓冲区通常会保持不变,但这是标准行为。
英文:
Consider the following code:
char buffer[5]{};
snprintf(buffer, sizeof(buffer), "hi");
snprintf
writes 'h'
, 'i'
and '\0'
to buffer
.
My question is: is there any guarantee that the snprintf
won't touch buffer[3]
and buffer[4]
according to the standard? Visual Studio 2019 keeps the unused buffer untouched, but is this a standard behavior?
答案1
得分: 2
以下是翻译好的部分:
N1548 草案 ISO/IEC 9899:201x 编程语言 — C
7.21.6.5 snprintf
函数
概要
#include <stdio.h>
int snprintf(char * restrict s, size_t n,
const char * restrict format, ...);
**描述**
2. **`snprintf`** 函数与 **`fprintf`** 等效,不同之处在于输出写入一个数组(由参数 **`s`** 指定),而不是写入流。如果 **`n`** 为零,则不写入任何内容,**`s`** 可以是空指针。否则,超过第 **`n-1`** 个位置的输出字符将被丢弃,而不会写入数组,并在实际写入数组的字符末尾写入空字符。如果在重叠的对象之间进行复制,则行为是未定义的。
**返回值**
3. **`snprintf`** 函数返回将会被写入的字符数,如果 **`n`** 足够大,不包括终止的空字符,或者如果发生编码错误则返回负值。因此,只有在返回值为非负且小于 **`n`** 时,才完全写入以空字符结尾的输出。
它清楚地定义了将写入多少字符。它不保证在返回值 + 1 后目标缓冲区中的字符不被修改。
如果在 POSIX 环境中运行代码,并且如果这种保证是必需的,可以使用使用 `fmemopen()` 打开的内存流,并与 `fprintf()` 一起使用。`fprintf()` 保证不会在终止空字符之后修改字符。
```c
char buffer[5]{};
FILE* f = fmemopen(buffer, sizeof(buffer), "w");
fprintf(f, "hi");
fclose(f);
英文:
The N1548 draft ISO/IEC 9899:201x Programming languages — C
> 7.21.6.5 The snprintf
function
>
> Synopsis
>
> 1. ```
> #include <stdio.h>
> int snprintf(char * restrict s, size_t n,
> const char * restrict format, ...);
> Description
>
> 2. The snprintf
function is equivalent to fprintf
, except that the output is written into an array (specified by argument s
) rather than to a stream. If n
is zero, nothing is written, and s
may be a null pointer. Otherwise, output characters beyond the n-1
<span/>st are discarded rather than being written to the array, and a null character is written at the end of the characters actually written into the array. If copying takes place between objects that overlap, the behavior is undefined.
>
> Returns
>
> 3. The snprintf
function returns the number of characters that would have been written had n
been sufficiently large, not counting the terminating null character, or a negative value if an encoding error occurred. Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n
.
It clearly defines how much characters would be written. It does not guarantee that characters are not modified in the target buffer after the returned value + 1.
If you run your code in POSIX environment and if such the guarantee is a requirement, you can use a memory stream opened with fmemopen()
and used with fprintf()
. fprintf()
guarantees that it will not modify characters after the terminating null character.
char buffer[5]{};
FILE* f = fmemopen(buffer, sizeof(buffer), "w");
fprintf(f, "hi");
fclose(f);
答案2
得分: 0
我无法想到一个原因,它会改变剩余空间中的内容。但如果你担心这一点,可以在代码中像下面这样调用snprintf()之前确定长度。
int main() {
char buffer[5]{};
char p[] = "hi";
size_t len = strlen(p);
size_t num = len < sizeof(buffer) ? len + 1 : sizeof(buffer);
snprintf(buffer, num, p);
return 0;
}
英文:
I cannot think of a reason that it will alter content in the remaining space. But if you are worried about that, determine the length before calling snprintf() in the code like below.
int main() {
char buffer[5]{};
char p[] = "hi";
size_t len = strlen(p);
size_t num = len < sizeof(buffer) ? len + 1 : sizeof(buffer);
snprintf(buffer, num, p);
return 0;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论