snprintf是否始终为null终止目标缓冲区?
换句话说,这是否足够:
char dst[10];
snprintf(dst, sizeof (dst), "blah %s", somestr);
Run Code Online (Sandbox Code Playgroud)
或者你必须这样做,如果somestr足够长?
char dst[10];
somestr[sizeof (dst) - 1] = '\0';
snprintf(dst, sizeof (dst) - 1, "blah %s", somestr);
Run Code Online (Sandbox Code Playgroud)
我对标准所说的以及一些流行的libc可能做的不是标准行为感兴趣.
Mar*_* Ba 67
正如其他答案所确定的那样:它应该:
snprintf...将结果写入字符串缓冲区.除非buf_size为零,否则(...)将以空字符终止.
所以你需要注意的是你没有将零大小的缓冲区传递给它,因为(显然)它不能将"零"写入"无处".
但是,要注意 Microsoft的库没有调用的函数,历史上只有一个函数调用snprintf但在_snprintf(注意前导下划线),它不附加终止空值.这是文档(VS 2012,~~ VS 2013):
http://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.110%29.aspx
回报价值
设len为格式化数据字符串的长度(不包括终止空值).len和count是_snprintf的字节数,_snwprintf是宽字符.
如果len <count,则len字符存储在缓冲区中,附加null终止符,并返回len.
如果len = count,则len字符存储在缓冲区中,不附加null-terminator,并返回len.
如果len> count,则count字符存储在缓冲区中,不附加空终止符,并返回负值.
(......)
Visual Studio 2015(VC14)显然引入了一致性snprintf函数,但具有前导下划线和非 null终止行为的遗留函数仍然存在:
snprintf当len大于或等于count时,该函数通过在null处放置null-terminator来截断输出buffer[count-1].(......)所有功能的其它比
snprintf,如果LEN =计数,len个字符被存储在缓冲器中,没有空终止符被附加,(...)
pio*_*otr 18
根据snprintf(3)手册页.
函数
snprintf()并vsnprintf()写入最多size字节(包括尾随空字节('\ 0'))str.
所以,是的,如果size> = 1则无需终止.
Jon*_*ler 10
根据C标准,除非缓冲器大小为0,vsnprintf()和snprintf()零终止其输出.
该
snprintf()函数应相当于sprintf(),加上n参数,该参数表示s引用的缓冲区的大小.如果n为零,则不应写入任何内容,并且s可能是空指针.否则,应丢弃超出n-1的输出字节而不是写入数组,并在实际写入数组的字节末尾写入空字节.
因此,如果您需要知道要分配的缓冲区大小,请使用零大小,然后可以使用空指针作为目标.请注意,我链接到POSIX页面,但是这些明确表示标准C和POSIX之间没有任何分歧,它们涵盖相同的基础:
此参考页面上描述的功能与ISO C标准一致.此处描述的要求与ISO C标准之间的任何冲突都是无意的.本卷POSIX.1-2008符合ISO C标准.
警惕微软版本vsnprintf().当缓冲区中没有足够的空间时,它与标准C版本的行为完全不同(它返回-1,标准函数返回所需的长度).微软版本null在错误条件下终止其输出并不完全清楚,而标准C版本则如此.
另请注意您使用TR 24731安全功能的答案吗?(请参阅MSDN的Microsoft版本vsprintf_s())和Mac解决方案,以便安全替代不安全的C标准库函数?
一些旧版本的 SunOS 对 snprintf 做了一些奇怪的事情,并且可能没有以 NUL 终止输出,并且返回值与其他人所做的不匹配,但是过去 10 年中发布的任何内容都在做 C99 的事情说。