簡體   English   中英

C 中的 strtok_r 和 strtok_s 有什么區別?

[英]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數組並根據需要將其分解。 strchrstrspnstrcspn可以幫助執行此操作,或者您可以從頭開始處理數組。

只是為了澄清。 strtok在 Windows 中是線程安全的。 strtok使用TLS變量來維護每個線程的最后一個指針。 但是,您不能使用strtok對每個線程的多個令牌字符串進行交錯訪問。 strtok_rstrtok_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM