转自:http://blog.chinaunix.net/u/19782/showart_371379.html
今天使用snprintf函数时想到了:
strcpy, strncpy
strcmp, strncmp
strcat, strncat
sprintf, snprintf
最喜欢用的就是snprintf,
因为它会自动在后面加'/0'. 在网上看了一下. 原来VC中_snprintf不是这样的.
VC中的_snprintf函数并没有按
照这样的规定来做,它在输出缓冲区不够大时就不会输出结尾的'/0'(跟strncpy的行为类似)。所以要让上面的程序工作正常,必须做相应的修改。
char buf[5];
_snprintf(buf, 5, "This is a test string."); // buf
becomes "This ", buf[4] is ' '
buf[4] =
0; // buf[4] is '/0' now. 为了安全,
在windows下要手动添加
_snprintf(buf, 6, "This is a test string.");
// ERROR: buffer overflow
_snprintf(buf, 5, "abc"); // buf becomes
"abc", the value of buf[3] is '/0', buf[4] is undefined.
如果要保证可移植
性,就得按VC的写法,做一次对于标准来说很多余的"填0"的操作,再通过定义宏来区别平台分别选用snprintf或_snprintf。
一个小的测试代码:
可以看到有两个地方不一样:
1>.
结尾的'/0'处理!
2>. 函数返回值不一样!
#
include
<
stdio.
h>
#
include
<
string
.
h>
#
define
STR_LEN 32
#
ifdef
_WIN32
#
define
snprintf _snprintf
#
endif
/**
* dump string
*/
static
void
dump_str(
const
char
*
title,
const
char
*
str,
int
len)
{
int
i;
printf
(
"%s[%d].%p
/n"
,
title,
len,
str)
;
for
(
i =
0;
i <
len;
i+
+
)
printf
(
"<%c,%02x>"
,
str[
i]
,
(
unsigned
char
)
str[
i]
)
;
printf
(
"/n"
)
;
}
int
main(
int
argc,
char
*
*
argv)
{
int
t;
char
str1[
STR_LEN]
,
str2[
STR_LEN]
;
strcpy
(
str1,
"123456789"
)
;
dump_str(
"str1"
,
str1,
STR_LEN)
;
t =
snprintf(
str2,
STR_LEN,
"%s"
,
str1)
;
dump_str(
"str2"
,
str2,
STR_LEN)
;
printf
(
"snprintf()
ret.%d /n"
,
t)
;
t =
snprintf(
str2,
5,
"%s"
,
str1)
;
dump_str(
"str2"
,
str2,
STR_LEN)
;
printf
(
"snprintf()
ret.%d /n"
,
t)
;
return
(
0)
;
}
/*
Test Env:
gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)
Result:
str1[32].0xbffb9190
<1,31><2,32><3,33><4,34><5,35><6,36><7,37><8,38><9,39><
,00><?fb><?bf><?d5><?82><,04><,08><
,00>< ,00>< ,00>< ,00>< ,00>< ,00><
,00><
,00><?c8><?91><?fb><?bf><&,26><?85><,04><,08>
str2[32].0xbffb9170
<1,31><2,32><3,33><4,34><5,35><6,36><7,37><8,38><9,39><
,00><w,77><,01><
,00><?92><?fb><?bf><?f8><d,64><?ad><
,00>< ,00>< ,00>< ,00>< ,00>< ,00><
,00>< ,00>< ,00>< ,00>< ,00>< ,00><
,00>
snprintf() ret.9
str2[32].0xbffb9170
<1,31><2,32><3,33><4,34><
,00><6,36><7,37><8,38><9,39><
,00><w,77><,01><
,00><?92><?fb><?bf><?f8><d,64><?ad><
,00>< ,00>< ,00>< ,00>< ,00>< ,00><
,00>< ,00>< ,00>< ,00>< ,00>< ,00><
,00>
snprintf() ret.9
-------------------------------------------------------------------------
Test Env:
Microsoft Windows XP [版本 5.1.2600]
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for
80x86
Result:
str1[32].0012FF60
<1,31><2,32><3,33><4,34><5,35><6,36><7,37><8,38><9,39><
,00><,12>< ,00><,10><,1d><@,40><
,00>< ,00><,08>< ,00>< ,00><,04><
,00>< ,00>< ,00>< ,00>< ,00>< ,00><
,00><?e0><,1e><@,40>< ,00>
str2[32].0012FF3C
<1,31><2,32><3,33><4,34><5,35><6,36><7,37><8,38><9,39><
,00><?93><|,7c><,ff><,ff><,ff><,ff><?eb><,06><?93><|,7c><?ef><0,30><@,40><
,00>< ,00>< ,00><7,37><
,00>< ,09>< ,00>< ,00>< ,00>
snprintf() ret.9
str2[32].0012FF3C
<1,31><2,32><3,33><4,34><5,35><6,36><7,37><8,38><9,39><
,00><?93><|,7c><,ff><,ff><,ff><,ff><?eb><,06><?93><|,7c><?ef><0,30><@,40><
,00>< ,00>< ,00><7,37><
,00>< ,09>< ,00>< ,00>< ,00>
snprintf() ret.-1
*/