众所周知,sprintf不能检查目标字符串的长度,可能造成众多安全问题,所以都会推荐使用snprintf.


snprintf(_snprintf)的声明是这样的




int _snprintf(

char *

buffer

,

size_t

count

,

const char *

format

[,


argument

] ...

);


If

len

<

count

, then

len

characters are stored in

buffer

, a null-terminator is appended, and

len

is returned.

If

len

=

count

, then

len

characters are stored in

buffer

, no null-terminator is appended, and

len

is returned.

If

len

>

count

, then

count

characters are stored in

buffer

, no null-terminator is appended, and a negative value is returned.


最常见的错误用法有:


1.

char sa[256]={0};

_snprintf(sa,sizeof(sa),"%s",sb);

//错误原因:当sb的长度>=256的时候,sa将没有'/0'结尾

2.

char sa[256];

_snprintf(sa,sizeof(sa)-1,"%s",sb);

//错误原因:当sb的长度>=255的时候,sa将没有'/0'结尾,忘记给sa初始化

3.

char sa[256];

_snprintf(sa,sizeof(sa)-1,"%s",sb);

sa[sizeof(sa)]=0;

//错误原因:最后一行数组越界


正确的用法


1. //推荐用法

char sa[256];

sa[sizeof(sa)-1]=0;

_snprintf(sa,sizeof(sa),"%s",sb);

if(sa[sizeof(sa)-1]!=0)

{

printf("warning:string will be truncated");

sa[sizeof(sa)-1]=0;

}

2.

char sa[256]={0};

int result = _snprintf(sa,sizeof(sa),"%s",sb);

if(result==sizeof(sa) || result<0)

{

printf("warning:sting will be truncated");

sa[sizeof(sa)-1]=0;

}

========================



int snprintf(char *restrict buf, size_t n, const char * restrict


format, ...);


函数说明:最多从源串中拷贝



n







1



个字符到目标串中,然后再在后面加一个



0



。所以如果目标串的大小为



n




的话,将不会溢出。


函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。




Result1(



推荐的用法



)





#include <stdio.h>

#include <stdlib.h>





int main()

{

char str[10]={0,};

snprintf(

str, sizeof(str


)

, "0123456789012345678");

printf("str=%s/n", str);

return 0;

}




root] /root/lindatest

$ ./test

str=012345678




Result2:(不推荐使用)





#include <stdio.h>

#include <stdlib.h>





int main()

{

char str[10]={0, };

snprintf(str, 18, "0123456789012345678");

printf("str=%s/n", str);

return 0;

}




root] /root/lindatest

$ ./test

str=01234567890123456




snprintf函数返回值的测试:




#include <stdio.h>

#include <stdlib.h>



int main()

{

char str1[10] ={0, };

char str2[10] ={0, };

int ret1=0,ret2=0;

ret1=snprintf(str1, sizeof(str1), "%s", "abc");

ret2=snprintf(str2, 4, "%s", "aaabbbccc");

printf("aaabbbccc length=%d/n", strlen("aaabbbccc"));

printf("str1=%s,ret1=%d/n", str1, ret1);

printf("str2=%s,ret2=%d/n", str2, ret2);

return 0;

}



[root] /root/lindatest

$ ./test

aaabbbccc length=9

str1=abc,ret1=3

str2=aaa,ret2=9

====================================

这个函数的格式跟printf的是差不多一样的,

不过在gcc里面,好像那个0是没用的,左边不会补0,会补空格,

具体格式在后文,

这是我试验的代码:

1 #include <stdio.h>

2

3 int main(void)

4 {

5     char array[20];

6     char *str = "1234";

7

8     snprintf(array, sizeof(array), "%08.8s", str);

9     printf("%s", array);

10     getchar();

11 }

----------------------------------------------------------

duck@duck ~/c $ gcc -o sn snprintf.c

snprintf.c: In function ‘main’:

snprintf.c:8: warning: '0' flag used with ‘%s’ gnu_printf format

snprintf.c:8: warning: '0' flag used with ‘%s’ gnu_printf format

duck@duck ~/c $ ./sn

1234

----------------------------------------------------------

由上面的输出看到左边补的确实是空格.

格式的具体含义:

.8 表示:显示精度,对于字符串,用于指定从字符串左侧开始截取的子串字符个数,也就是说,str只取前8个字符,

08 表示:最小域宽,若为正整数,当输出数据宽度小于设定值时,在域内向右靠齐,左边多余位补空格,当输出数据宽度大于设定值时,按实际宽度全部输出,

若有前导符0(08 的那个0),则左边多余位补0(不是空格)

若最小域宽为负整数,输出数据在域内向左靠齐.

原文: 谈谈snprintf