snprintf/_snprintf 在不同平臺間函數差異

文章一: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就是要寫入的總字符串字符數,例如:
    
None.gif//VC
None.gif
int main(int argc, char * argv[])
ExpandedBlockStart.gif
...
{
InBlock.gif    
char   buff[100
];
InBlock.gif     printf(
"%d ",_snprintf(buff,10,"1234567890ab"
));
InBlock.gif     printf(
"%s"
,buff);
InBlock.gif    
return 0
;
ExpandedBlockEnd.gif}

None.gif
None.gif
//Linxu:gcc/g++
None.gif
#include <stdio.h>
None.gif
int main(int argc, char * argv[])
ExpandedBlockStart.gif
...
{
InBlock.gif    
char   buff[100
];
InBlock.gif     printf(
"%d ",snprintf(buff,10,"1234567890ab"
));
InBlock.gif     printf(
"%s"
,buff);
InBlock.gif    
return 0
;
ExpandedBlockEnd.gif}
 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.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章