2012-09-14 63 views
1

我正在將一個win32應用程序移植到linux,而不是每個_snprintf_s都有一堆#ifdefs,我想知道是否有辦法#以某種方式將其定義爲snprintf。#define _snprintf_s to snprintf

因此,像 -

#define _snprintf_s(1,2,3,4,5) snprintf(1,2,4,5) 

第三個參數,最大字符數來存儲,或_TRUNCATE不存在的snprintf的。

這種方法是否正確?我可以做這樣的#定義嗎? 如果是這樣,有人可能會指出我應該如何去做?我想通過this question知道我必須小心這些#defines。

謝謝!

+0

對於初學者來說,你不能用數字作爲宏參數名稱;他們必須是標識符。 –

+2

我打算建議在Windows中使用'_snprintf',在Linux中使用'snprintf',但微軟的'_snprintf'函數與標準'snprintf'不相當。特別是,'_snprintf'可以不用'''0'終止符而離開目標緩衝區。 –

回答

3

#define _snprintf_s(a,b,c,...) snprintf(a,b,__VA_ARGS__)

+0

感謝您的回覆!我嘗試了你的建議,它的工作。 – sskanitk

+0

這可能會導致錯誤,因爲MS的附錄K函數提供了終止符,如果緩衝區已滿,snprintf不會執行。移植後的代碼可能會因此而出現故障 – Rob11311

+0

@ Rob11311:除非'n'爲零,否則snprintf'始終終止,在這種情況下,它什麼都不寫。您的信息根本不正確。閱讀C99。 –

4

取而代之的是宏觀的,你可以實現_snprintf_s()的功能。這個簡單的(未經測試的)版本不會執行_snprintf_s()應該執行的運行時錯誤處理(如果需要,您可以添加該錯誤處理),但它會嘗試處理count參數強加的差異以及截斷時的返回值:

#include <assert.h> 
#include <stdarg.h> 
#include <stdio.h> 
#include <string.h> 

#if !defined(_TRUNCATE) 
#define _TRUNCATE ((size_t)-1) 
#endif 

int _snprintf_s(
    char *buffer, 
    size_t sizeOfBuffer, 
    size_t count, 
    const char *format, 
    ... 
) 
{ 
    int retval; 
    va_list ap; 

    if ((count != _TRUNCATE) && (count < sizeOfBuffer)) { 
     sizeOfBuffer = count; 
    } 

    va_start(ap, format); 
    retval = vsnprintf(buffer, sizeOfBuffer, format, ap); 
    va_end(ap); 

    if ((0 <= retval) && (sizeOfBuffer <= (size_t) retval)) { 
     retval = -1; 
    } 

    return retval; 
} 

(?爲什麼count參數在首位_snprintf_s()參數列表)

+0

感謝您的實施。實際上,我確實只需要一個等效的snprintf,並按照下面提供的答案中提出的方法,似乎正在做我所需要的。 – sskanitk

+0

用於最終括號內的註釋。我無法理解MS「邊界檢查接口」和它們所採用的重複長度/計數參數。也許這個想法是,如果你必須兩次寫目標緩衝區大小,你更有可能得到它的權利......? –

+0

MS函數做一個「砍」,以確保截斷的字符串是NULL終止。 – Rob11311