来自 https://stackoverflow.com/a/13067917/156458
snprintf ... Writes the results to a character string buffer. (...) will be terminated with a null character, unless buf_size is zero.
那么,为什么 Linux 编程接口(interface)中的以下示例将字符串的最后一个字符(由 snprintf()
分配)显式设置为 \0
?
char *
inetAddressStr(const struct sockaddr *addr, socklen_t addrlen,
char *addrStr, int addrStrLen)
{
char host[NI_MAXHOST], service[NI_MAXSERV];
if (getnameinfo(addr, addrlen, host, NI_MAXHOST,
service, NI_MAXSERV, NI_NUMERICSERV) == 0)
snprintf(addrStr, addrStrLen, "(%s, %s)", host, service);
else
snprintf(addrStr, addrStrLen, "(?UNKNOWN?)");
addrStr[addrStrLen - 1] = '\0'; /* Ensure result is null-terminated */
return addrStr;
}
最佳答案
如果 snprintf
符合 C 标准,则将目标数组的最后一个字符显式设置为 '\0'
似乎没有用。
但是请注意,Linux 内核使用自己的 C 库版本,该版本可能符合也可能不符合 C 标准。大多数函数都早于首次指定 snprintf
的 C99 标准,这可能解释了实现差异。内核的 snprintf
实现的当前版本确实设置了空终止符。发布的代码似乎来自用户代码,而不是内核代码,所以这无关紧要。
另请注意,某些 C 库具有非标准行为。例如,Microsoft C 运行时库在发布后将近 15 年不支持 C99 扩展,并且由于各种原因仍然不完全符合。例如,snprintf
对于 %n
转换具有非标准行为。
另请注意,某些与标准函数名称非常相似的 Microsoft 扩展的行为方式令人惊讶且令人困惑。例如,如果输出被截断,_snprintf()
将不会在目标数组中设置空终止符。见this documentation page血淋淋的细节。
对于发布的代码,C 库不太可能来自 Microsoft,但 linux 内核可能用于具有各种 C 库的系统:GNU libc 用于大多数桌面发行版,但 Android 例如使用不同的图书馆。代码片段的作者:
- 不完全理解 C 标准并编写了冗余代码。
- 不信任本地 C 库的实现,并且不想假设
snprintf
编写了空终止符。 - 习惯使用防御性编程并编写冗余代码以防万一。
关于c - 为什么此示例明确地将字符串的最后一个字符(由 `snprintf()` 分配)设置为 `/0` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54970552/