[英]What's the difference between strtok_r and strtok_s in C?
我正在嘗試在需要能夠在 Linux 和 Windows 中編譯的 C 程序中使用此函數。 起初我嘗試使用 strtok_r,但是當我在 Windows 上編譯時,它抱怨該函數不存在並說它會假設它是一個外部函數,但后來失敗了。 然后我使用 strtok_s 並編譯! 然后我在 Linux 上嘗試,但現在它抱怨有一個“對'strtok_s'的未定義引用”。
一個是windows唯一的函數,另一個是linux函數??? 我該怎么做才能讓它在兩者上編譯?
strtok_s
簡直就是Windows版本的strtok_r
這是標准的其他地方。
在涉及strtok_s
/ strtok_r
類的函數時,使程序具有可移植性的一種(我認為很常見)方法是使用預處理器:
#if defined(_WIN32) || defined(_WIN64)
/* We are on Windows */
# define strtok_r strtok_s
#endif
由於原型和功能相同,您現在只能使用strtok_r
。
我沒有足夠的聲譽來評論其他答案,所以我必須提供我自己的。
1) 要解決此聲明:
“strtok_s 是 Windows 上 strtok 的緩沖區溢出安全版本。Windows 上的標准 strtok 是線程安全的......”
這不是真的。 strtok_s 是 MSVC 編譯器的線程安全版本。 strtok 不是線程安全的!
2) 要解決此聲明:
“如果在 Cygwin 上編譯它可能會中斷,Cygwin 將自身報告為 Windows,但已經定義了
strtok_r
等 POSIX 接口。”
再次,不是真的。 不同之處在於您使用的編譯器。 使用 Microsoft 的 Visual C++ 編譯器 MSVC 時,函數為strtok_s.
另一個編譯器,例如 GNU Compiler Collection, GCC,可能使用不同的標准庫實現,例如strtok_r
。 在確定要使用的函數時,請考慮編譯器,而不是目標平台。
在我看來,Joachim Pileborg 的回答是這一頁上最好的回答。 但是,它需要一個小的編輯:
#if defined(_WIN32) /* || defined(_WIN64) */
#define strtok_r strtok_s
#endif
_WIN32 和 _WIN64 都是 MSVC 編譯器提供的預定義宏。 _WIN64 在編譯 64 位目標時定義。 _WIN32 是為 32 位和 64 位目標定義的。 這是 Microsoft 為向后兼容性所做的妥協。 _WIN32 被創建來指定 Win32 API。 現在您應該考慮使用 _WIN32 來指定 Windows API——它不是特定於 32 位目標。
這兩個函數對於解析字符串來說都是非常丑陋、不直觀的習慣用法,並且通常無法以微妙的方式滿足特定應用程序的要求。 對於標准 C 中的普通strtok
。只需將它們扔掉並編寫您自己的代碼來迭代char
數組並根據需要將其分解。 strchr
、 strspn
和strcspn
可以幫助執行此操作,或者您可以從頭開始處理數組。
只是為了澄清。 strtok
在 Windows 中是線程安全的。 strtok
使用TLS
變量來維護每個線程的最后一個指針。 但是,您不能使用strtok
對每個線程的多個令牌字符串進行交錯訪問。 strtok_r
和strtok_s
都通過允許用戶通過第三個參數維護上下文來解決這個交織問題。 希望這可以幫助。
strtok_r 是 POSIX 系統上 strtok 的線程安全版本
strtok_s是 Windows 上 strtok 的緩沖區溢出安全版本。 Windows 上的標准 strtok 是線程安全的,所以 strtok_s 應該是。
MinGW 也預定義了_WIN32
但它支持strtok_r
,所以我認為檢查_WIN32
宏不是一個好主意。 最好檢查_MSC_VER
宏,這是Microsoft Visual Studio 的宏。
#ifdef _MSC_VER
#define strtok_r strtok_s
#endif
警告:Microsoft strtok_s
和 C11 strtok_s
完全不同! 微軟的strtok_s
只有3個參數,而C11 strtok_s
有4個參數,所以以后可能會出現兼容問題。
微軟strtok_s
的原型是
char* strtok_s(char* str, const char* delimiters, char** context);
C11 strtok_s
的原型是
char *strtok_s(char *restrict str, rsize_t *restrict strmax, const char *restrict delim, char **restrict ptr);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.