snprintf/_snprintf 在不同平台间函数差异

时间:2021-05-01 04:01:14

文章一:http://www.cppblog.com/sandy/archive/2006/09/29/13133.html

谈谈snprintf

 

众所周知,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;
}

Windows:

char sa[2];
char sb[3]="aa";
_snprintf(sa, sizeof(sa), "%s/0", sb);

==> sa="aa",但是没有'/0'结束

 

Linux:

char sa[2];
char sb[3]="aa";
snprintf(sa, sizeof(sa), "%s", sb);
这样用的, 而且sa=>"a", 系统会自动截断

 

 

文章二:snprintf/_snprintf 在不同平台间函数差异

http://hi.baidu.com/xinzsky/blog/item/5e03981f828c9bf6e1fe0bf3.html

 

 

2007-11-20 17:25

snprintf函数并不是标准c/c++中规定的函数,但是在许多编译器中,厂商提供了其实现的版本。
在gcc中,该函数名称就snprintf,而在VC中称为_snprintf。
  由于不是标准函数,没有一个统一的标准来规定该函数的行为,所以导致了各厂商间的实现版本可
能会有差异。今天也的的确确看到了差异,因为这个小小的差异是我的程序无法正常的处理数据。
  这个小小的差异发生在count参数。在VC中,这个count就是要写入的总字符串字符数,例如:
    
snprintf/_snprintf 在不同平台间函数差异//VC
snprintf/_snprintf 在不同平台间函数差异
int main(int argc, char * argv[])
snprintf/_snprintf 在不同平台间函数差异snprintf/_snprintf 在不同平台间函数差异
...
{
snprintf/_snprintf 在不同平台间函数差异    
char   buff[100
];
snprintf/_snprintf 在不同平台间函数差异     printf(
"%d ",_snprintf(buff,10,"1234567890ab"
));
snprintf/_snprintf 在不同平台间函数差异     printf(
"%s"
,buff);
snprintf/_snprintf 在不同平台间函数差异    
return 0
;
snprintf/_snprintf 在不同平台间函数差异}

snprintf/_snprintf 在不同平台间函数差异
snprintf/_snprintf 在不同平台间函数差异
//Linxu:gcc/g++
snprintf/_snprintf 在不同平台间函数差异
#include <stdio.h>
snprintf/_snprintf 在不同平台间函数差异
int main(int argc, char * argv[])
snprintf/_snprintf 在不同平台间函数差异snprintf/_snprintf 在不同平台间函数差异
...
{
snprintf/_snprintf 在不同平台间函数差异    
char   buff[100
];
snprintf/_snprintf 在不同平台间函数差异     printf(
"%d ",snprintf(buff,10,"1234567890ab"
));
snprintf/_snprintf 在不同平台间函数差异     printf(
"%s"
,buff);
snprintf/_snprintf 在不同平台间函数差异    
return 0
;
snprintf/_snprintf 在不同平台间函数差异}
 vc程序的输出是:
-1
1234567890@
gcc程序的输出是:
12
123456789
从输出结果可以知道:VC中的_snprintf的count参数表示,会向buff中写入count个字符,不包括'/0'字符,
并且不会在字符串末尾添加'/0'符,并且,如果字符串超过count,函数返回-1以标志可能导致的错误;gcc
中的snprintf函数的count参数表示,向buff中写入10个字符,包括'/0'字符,并且,返回实际的字符串长度,
例子中为12。
  如果不了解这些函数在各平台间的差异,也许我们的程序在移植过程中会变得很脆弱。我们应该小心各种各样
的陷阱。

下面是MSDN对_snprintf函数的解释:

int _snprintf( char *, size_t , const char * [, ] ... );

Parameters

buffer
Storage location for output
count
Maximum number of characters to store
format
Format-control string
argument
Optional arguments

Libraries

All versions of the C run-time libraries.

Return Value

_snprintf returns the number of bytes stored in buffer, not counting the terminating null character. If the number of bytes required to store the data exceeds count, then count bytes of data are stored in buffer and a negative value is returned.

Remarks

The _snprintf function formats and stores count or fewer characters and values (including a terminating null character that is always appended unless count is zero or the formatted string length is greater than or equal to count characters) in buffer. Each argument (if any) is converted and output according to the corresponding format specification in format. The format consists of ordinary characters and has the same form and function as the format argument for printf. If copying occurs between strings that overlap, the behavior is undefined.