web-dev-qa-db-fra.com

Quelle est la différence entre strtok_r et strtok_s en C?

J'essaie d'utiliser cette fonction dans un programme C qui doit pouvoir compiler sous Linux et Windows. Au début, j’ai essayé d’utiliser strtok_r, mais lorsque j’ai compilé sous Windows, il s’est plaint de l’absence de la fonction et dit qu’il supposerait qu’il s’agit d’une fonction externe, mais a échoué. J'ai ensuite utilisé strtok_s et c'est compilé! Ensuite, j'ai essayé sur Linux, mais maintenant, on se plaint de l'existence d'une "référence non définie à 'strtok_s'".

Est-ce que l'une des fenêtres ne fonctionne que et l'autre une fonction Linux ??? Que puis-je faire pour le compiler sur les deux?

19
petranaya

Ces deux fonctions sont des idiomes vraiment laids et non intuitifs pour l'analyse de chaînes, et ne répondent généralement pas aux exigences de votre application particulière de manière subtile. Même plus pour la simple strtok en standard C. Jetez-les simplement et écrivez votre propre code pour le parcourir sur le tableau char et le diviser au besoin. strchr, strspn et strcspn peuvent être utiles, ou vous pouvez simplement travailler à partir de zéro sur le tableau.

9
R..

strtok_s est simplement la version Windows de strtok_r qui est standard partout ailleurs.

Une façon (courante, je pense) de rendre un programme portable en ce qui concerne des fonctions telles que strtok_s/strtok_r est d’utiliser le pré-processeur:

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

Les prototypes et les fonctionnalités étant identiques, vous ne pouvez désormais utiliser que strtok_r.

31

Je n'ai pas assez de réputation pour commenter d'autres réponses, je vais donc devoir fournir les miennes.

Pour adresser cette déclaration:

"strtok_s est une version sûre de Strtok sous Windows en cas de débordement de tampon. Le strtok standard sous Windows est thread-safe ..."

Ce n'est pas vrai. strtok_s est la version thread-safe du compilateur MSVC. strtok n'est pas thread-safe!

Pour adresser cette déclaration:

"Cela casserait probablement si on compilait sur cygwin qui se présente comme une fenêtre mais dont les interfaces posix comme strtok_r sont déjà définies."

Encore une fois, pas vrai. La différence est quel compilateur vous utilisez. Lorsque vous utilisez le compilateur Visual C++ de Microsoft, MSVC, la fonction est strtok_s. Un autre compilateur, tel que la collection de compilateurs GNU, GCC, peut utiliser une implémentation de bibliothèque standard différente, telle que strtok_r. Pensez au compilateur, et non à la plate-forme cible, pour identifier la fonction à utiliser.

À mon avis, la réponse de Joachim Pileborg est la meilleure sur cette page. Cependant, il faut une petite modification:

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

_WIN32 et _WIN64 sont des macros prédéfinies fournies par le compilateur MSVC. _WIN64 est défini lors de la compilation d'une cible 64 bits. _WIN32 est défini pour les cibles 32 et 64 bits. Il s'agit d'un compromis fait par Microsoft pour assurer la compatibilité avec les versions antérieures. _WIN32 a été créé pour spécifier l'API Win32. A présent, vous devez considérer que _WIN32 spécifie une API Windows - elle n'est pas spécifique à une cible 32 bits.

9
BeReal82

Juste pour clarifier. strtok est thread-safe sous Windows. strtok utilise une variable TLS pour conserver le dernier pointeur de chaque thread. Cependant, vous ne pouvez pas utiliser strtok pour entrelacer l’accès à plus d’une chaîne de jetons par thread. strtok_r et strtok_s répondent tous deux à ce problème d'entrelacement en permettant à l'utilisateur de conserver le contexte via le troisième paramètre. J'espère que cela t'aides.

4
Jamey Kirby

strtok_r est une version thread-safe de strtok sur les systèmes POSIX

strtok_s est une version sécurisée de la mémoire tampon de strtok sous Windows. Le strtok standard sur Windows est thread-safe, donc strtok_s devrait l'être.

4
Martin Beckett

MinGW prédéfinit également _WIN32 mais il supporte strtok_r, donc je ne pense pas que ce soit une bonne idée de vérifier la macro _WIN32. Il est préférable de vérifier la macro _MSC_VER, qui est la macro pour Microsoft Visual Studio.

#ifdef _MSC_VER
#define strtok_r strtok_s
#endif

AVERTISSEMENT: Microsoft strtok_s et C11 strtok_s sont complètement différents! Microsoft strtok_s n'a que 3 paramètres, alors que C11 strtok_s en a 4, il peut donc s'agir d'un problème compatible à l'avenir.

Le prototype de Microsoft strtok_s est

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

Le prototype de C11 strtok_s est

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