it-swarm.com.de

Was ist der Unterschied zwischen strtok_r und strtok_s in C?

Ich versuche, diese Funktion in einem C-Programm zu verwenden, das in Linux und Windows kompiliert werden muss. Zuerst habe ich versucht, strtok_r zu verwenden, aber dann, als ich unter Windows kompiliert habe, hat es sich über die nicht vorhandene Funktion beschwert und gesagt, es sei eine externe Funktion, aber dann ist es fehlgeschlagen. Ich habe dann strtok_s benutzt und es kompiliert! Dann habe ich es mit Linux versucht, aber jetzt beschwert es sich, dass es einen "undefinierten Verweis auf 'strtok_s'" gibt.

Ist einer eine Windows-Funktion und der andere eine Linux-Funktion ??? Was kann ich tun, um es auf beiden zu kompilieren?

19
petranaya

Diese beiden Funktionen sind wirklich hässliche, unintuitive Redewendungen für das Parsen von Zeichenfolgen und erfüllen die Anforderungen Ihrer jeweiligen Anwendung normalerweise nicht auf subtile Weise. Sogar mehr für die einfache strtok in Standard C. Werfen Sie sie einfach raus und schreiben Sie Ihren eigenen Code, um über das char-Array zu iterieren und es nach Bedarf aufzuteilen. strchr, strspn und strcspn können dabei hilfreich sein, oder Sie können das Array einfach von Grund auf bearbeiten.

9
R..

strtok_s ist einfach die Windows-Version von strtok_r, die sonst überall Standard ist.

Eine (meiner Meinung nach übliche) Möglichkeit, ein Programm für Funktionen wie strtok_s/strtok_r portabel zu machen, ist die Verwendung des Präprozessors:

#if defined(_WIN32) || defined(_WIN64)
/* We are on Windows */
# define strtok_r strtok_s
#endif

Da die Prototypen und Funktionen identisch sind, können Sie nur noch strtok_r verwenden.

31

Ich habe nicht genug Reputation, um andere Antworten zu kommentieren, daher muss ich meine eigenen zur Verfügung stellen.

Um diese Aussage zu adressieren:

"strtok_s ist eine pufferüberlaufsichere Version von strtok unter Windows. Das Standard-strtok unter Windows ist threadsicher ..."

Das ist nicht wahr. strtok_s ist die thread-sichere Version für den MSVC-Compiler. strtok ist nicht threadsicher!

Um diese Aussage zu adressieren:

"Dies würde wahrscheinlich scheitern, wenn das Kompilieren auf Cygwin, das sich selbst als Windows meldet, aber bereits definierte Posix-Schnittstellen wie strtok_r hat."

Wieder nicht wahr. Der Unterschied ist, welchen Compiler Sie verwenden. Wenn Sie den Microsoft Visual C++ - Compiler MSVC verwenden, lautet die Funktion strtok_s. Ein anderer Compiler, wie die GNU Compiler Collection, GCC, verwendet möglicherweise eine andere Standardbibliotheksimplementierung wie strtok_r. Denken Sie beim Ermitteln der zu verwendenden Funktion an den Compiler und nicht an die Zielplattform.

Die Antwort von Joachim Pileborg ist meiner Meinung nach die beste auf dieser Seite. Es bedarf jedoch einer kleinen Bearbeitung:

#if defined(_WIN32) /* || defined(_WIN64) */
#define strtok_r strtok_s
#endif

Sowohl _WIN32 als auch _WIN64 sind vordefinierte Makros, die vom MSVC-Compiler bereitgestellt werden. _WIN64 wird beim Kompilieren eines 64-Bit-Ziels definiert. _WIN32 ist für 32- und 64-Bit-Ziele definiert. Dies ist ein Kompromiss, den Microsoft aus Gründen der Abwärtskompatibilität eingegangen ist. _WIN32 wurde erstellt, um die Win32-API anzugeben. Jetzt sollten Sie _WIN32 in Betracht ziehen, um die Windows-API anzugeben - diese ist nicht spezifisch für ein 32-Bit-Ziel.

9
BeReal82

Nur um klarzustellen. strtok ist unter Windows threadsicher. strtok verwendet eine TLS-Variable, um den letzten Zeiger für jeden Thread zu verwalten. Sie können jedoch strtok nicht verwenden, um den Zugriff auf mehr als eine Tokenzeichenfolge pro Thread zu verschachteln. Sowohl strtok_r als auch strtok_s lösen dieses Verschachtelungsproblem, indem der Benutzer den Kontext über den dritten Parameter verwalten kann. Hoffe das hilft.

4
Jamey Kirby

strtok_r ist eine thread-sichere Version von strtok auf POSIX-Systemen

strtok_s ist eine pufferüberlaufsichere Version von strtok unter Windows. Das Standard-Strtok unter Windows ist thread-sicher, so sollte strtok_s sein.

4
Martin Beckett

MinGW gibt auch _WIN32 vor, unterstützt jedoch strtok_r. Daher halte ich es nicht für eine gute Idee, das _WIN32-Makro zu überprüfen. Es ist besser, das Makro _MSC_VER zu überprüfen, das das Makro für Microsoft Visual Studio ist.

#ifdef _MSC_VER
#define strtok_r strtok_s
#endif

ACHTUNG: Microsoft strtok_s und C11 strtok_s sind völlig unterschiedlich! Microsoft strtok_s hat nur 3 Parameter, während C11 strtok_s 4 Parameter hat, sodass es in Zukunft ein kompatibles Problem sein kann.

Der Prototyp von Microsoft strtok_s ist

char* strtok_s(char* str, const char* delimiters, char** context);

Der Prototyp von C11 strtok_s ist

char *strtok_s(char *restrict str, rsize_t *restrict strmax, const char *restrict delim, char **restrict ptr);
0
Victor