Подтвердить что ты не робот

Какая разница между strtok_r и strtok_s в C?

Я пытаюсь использовать эту функцию в программе на C, которая должна быть в состоянии скомпилировать в Linux и Windows. Сначала я попытался использовать strtok_r, но затем, когда я скомпилировал на windows, он жаловался на функцию, которая не существует, и сказала, что будет считать ее внешней функцией, но затем не удалась. Затем я использовал strtok_s и скомпилировал его! Затем я попробовал Linux, но теперь он жалуется, что есть ссылка "undefined на" strtok_s ".

Является ли функция только для Windows, а другая - функцией linux??? Что я могу сделать, чтобы скомпилировать оба?

4b9b3361

Ответ 1

Обе эти функции являются действительно уродливыми, неинтуитивными идиомами для синтаксического анализа строк и обычно не соответствуют вашим конкретным требованиям приложений тонким образом. Даже более простой для обычного strtok в стандартном C. Просто выкиньте их и напишите свой собственный код, чтобы перебрать массив char и разбить его по мере необходимости. strchr, strspn и strcspn могут быть полезны в этом, или вы можете просто работать с нуля на массиве.

Ответ 2

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.

Ответ 3

У меня недостаточно репутации, чтобы комментировать другие ответы, поэтому я должен предоставить свой собственный.

1) Для решения этого заявления:

"strtok_s - это безопасная версия strtok для Windows, защищенная от переполнения буфера. Стандартный strtok для Windows является поточно-ориентированным..."

Это неправда. strtok_s - это потокобезопасная версия для компилятора MSVC. strtok не является поточно-ориентированным!

2) Для решения этого заявления:

"Это, вероятно, strtok_r бы при компиляции на Cygwin, который сообщает о себе как о Windows, но имеет интерфейсы POSIX, такие как strtok_r уже определенные".

Опять не правда. Разница в том, какой компилятор вы используете. При использовании компилятора Microsoft Visual C++ MSVC используется функция strtok_s. Другой компилятор, такой как коллекция компиляторов GNU, GCC, может использовать другую реализацию стандартной библиотеки, такую как strtok_r. При определении того, какую функцию использовать, думайте о компиляторе, а не целевой платформе.

На мой взгляд, ответ Йоахима Пилеборга - лучший на этой странице. Однако, это требует небольшого редактирования:

#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-битной цели.

Ответ 4

strtok_r - это потоковая версия strtok для POSIX-систем.

strtok_s - это безопасная версия strtok в Windows для переполнения буфера. Стандартный strtok на окнах является потокобезопасным, поэтому strtok_s должен быть.

Ответ 5

Просто уточнить. strtok является потокобезопасным в Windows. strtok использует переменную TLS для поддержания последнего указателя для каждого потока. Однако вы не можете использовать strtok для чередования доступа к более чем одной строке токена в потоке. strtok_r и strtok_s обращаются к этой проблеме чередования, позволяя пользователю поддерживать контекст через третий параметр. Надеюсь, это поможет.

Ответ 6

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 совершенно разные! Microsoft strtok_s имеет только 3 параметра, в то время как C11 strtok_s имеет 4 параметра, поэтому в будущем это может стать проблемой совместимости.

Прототип Microsoft 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);