c - 为什么此示例明确地将字符串的最后一个字符(由 `snprintf()` 分配)设置为 `/0` ?

标签 c printf

来自 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/

相关文章:

c - 如何制作受正则表达式启发的字符串函数?

c - Matlab:帮助理解正弦曲线拟合

c - Windows 上的缓冲区溢出攻击导致访问冲突

php - 在 php printf 函数中更改表的颜色时发生错误

c - C编程的良好礼仪

linux - 将在 linux 中运行汇编代码的结果重定向到文本文件

c - Bash,如何检查 C 程序是否超时

c - 数组大小在运行时确定

linux - `' ` 在 `printf "%x""' 你"` 中的功能是什么?

c - 为什么这个浮点加法结果不正确?