在 printf-in 非 0 终止字符串中使用精度的可移植性
Portablilty of using percison when printf-ing non 0 terminated strings
正如这里的多个问题也指出的那样,您可以 printf
通过将精度格式化为要打印的最大长度来格式化一个未终止的字符串。像
printf("%.*s\n", length, str);
将从 str
(或直到第一个 0 字节)开始打印 length
个字符。
正如所指出的 here by jonathan-leffler, this is specified by posix here. And when reading the doc I discovered it actually never states this should work (or I couldn't find it) , as "The ‘%s’ conversion prints a string." and "A string is a null-terminated array of bytes [...] ". The regard about the precision states "A precision can be specified to indicate the maximum number of characters to write;".
我的解释是,上面的行实际上是未定义的行为,但是因为 printf
的实现是有效的,所以 read 比 写.
所以我的问题是:这个解释正确吗
TLDR:
我是否应该在尝试 posix 兼容时停止使用此 printf 技巧,因为存在一个可能导致缓冲区溢出的实现?
您正在阅读的不是实际的 POSIX 规范,而是 GNU libc 手册,为了便于阅读,它往往不太精确。可以在 https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html 找到实际的规范(它甚至 link 来自你 link 的 Jonathan Leffler 的回答),它清楚地表明你的代码是好的:
s
The argument shall be a pointer to an array of char. Bytes from the array shall be written up to (but not including) any terminating null byte. If the precision is specified, no more than that many bytes shall be written. If the precision is not specified or is greater than the size of the array, the application shall ensure that the array contains a null byte.
请注意,他们小心翼翼地不按照您指出的原因使用“字符串”一词。
ISO C17 标准使用几乎相同的语言,因此您的代码甚至可以移植到非 POSIX 标准 C 实现。 (POSIX 通常包含 ISO C,并且 POSIX 规范的许多部分来自 copy/pasted C 标准。)
正如这里的多个问题也指出的那样,您可以 printf
通过将精度格式化为要打印的最大长度来格式化一个未终止的字符串。像
printf("%.*s\n", length, str);
将从 str
(或直到第一个 0 字节)开始打印 length
个字符。
正如所指出的 here by jonathan-leffler, this is specified by posix here. And when reading the doc I discovered it actually never states this should work (or I couldn't find it) , as "The ‘%s’ conversion prints a string." and "A string is a null-terminated array of bytes [...] ". The regard about the precision states "A precision can be specified to indicate the maximum number of characters to write;".
我的解释是,上面的行实际上是未定义的行为,但是因为 printf
的实现是有效的,所以 read 比 写.
所以我的问题是:这个解释正确吗
TLDR: 我是否应该在尝试 posix 兼容时停止使用此 printf 技巧,因为存在一个可能导致缓冲区溢出的实现?
您正在阅读的不是实际的 POSIX 规范,而是 GNU libc 手册,为了便于阅读,它往往不太精确。可以在 https://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html 找到实际的规范(它甚至 link 来自你 link 的 Jonathan Leffler 的回答),它清楚地表明你的代码是好的:
s
The argument shall be a pointer to an array of char. Bytes from the array shall be written up to (but not including) any terminating null byte. If the precision is specified, no more than that many bytes shall be written. If the precision is not specified or is greater than the size of the array, the application shall ensure that the array contains a null byte.
请注意,他们小心翼翼地不按照您指出的原因使用“字符串”一词。
ISO C17 标准使用几乎相同的语言,因此您的代码甚至可以移植到非 POSIX 标准 C 实现。 (POSIX 通常包含 ISO C,并且 POSIX 规范的许多部分来自 copy/pasted C 标准。)