Linux C 中的 strtok_r 和 strtok_s 有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9021502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:14:19  来源:igfitidea点击:

What's the difference between strtok_r and strtok_s in C?

cwindowslinuxcompiler-errorsstrtok

提问by petranaya

I'm trying to use this function in a C program that needs to be able to compile in Linux and Windows. At first I tried using strtok_r, but then when I compiled on windows, it complained about the function not existing and said it would assume it's an extern function, but then failed. I then used strtok_s and it compiled! Then I tried on Linux but now it's complaining that there is an "undefined reference to 'strtok_s'".

我正在尝试在需要能够在 Linux 和 Windows 中编译的 C 程序中使用此函数。起初我尝试使用 strtok_r,但是当我在 Windows 上编译时,它抱怨该函数不存在并说它会假设它是一个外部函数,但后来失败了。然后我使用 strtok_s 并编译!然后我在 Linux 上尝试,但现在它抱怨有一个“对'strtok_s'的未定义引用”。

Is one a windows only function and the other a linux function??? What can I do to make it compile on both?

一个是windows唯一的函数,另一个是linux函数???我该怎么做才能让它在两者上编译?

采纳答案by R.. GitHub STOP HELPING ICE

Both of these functions are really ugly, unintuitive idioms for parsing strings, and usually fail to meet your particular application's requirements in subtle ways. Even moreso for the plain strtokin standard C. Just throw them out and write your own code to iterate over the chararray and break it up as needed. strchr, strspn, and strcspncan be helpful in doing this or you can just work from scratch on the array.

这两个函数对于解析字符串来说都是非常丑陋、不直观的习惯用法,并且通常无法以微妙的方式满足特定应用程序的要求。对于strtok标准 C 中的普通代码更是如此。只需将它们扔掉并编写自己的代码来迭代char数组并根据需要将其分解。strchr, strspn, 并且strcspn可以帮助执行此操作,或者您可以从头开始处理阵列。

回答by Martin Beckett

strtok_r is a thread safe version of strtok on POSIX systems

strtok_r 是 POSIX 系统上 strtok 的线程安全版本

strtok_sis a buffer overrun safe version of strtok on Windows. The standard strtok on windows is thread safe, so strtok_s should be.

strtok_s是 Windows 上 strtok 的缓冲区溢出安全版本。Windows 上的标准 strtok 是线程安全的,所以 strtok_s 应该是。

回答by Some programmer dude

strtok_sis simply the Windows version of strtok_rwhich is standard everywhere else.

strtok_s只是 Windows 版本,strtok_r在其他任何地方都是标准的。

One (common I would think) way to make a program portable when it comes to functions like strtok_s/strtok_ris to use the preprocessor:

当涉及到strtok_s/ 之类的功能时,使程序可移植的一种(我认为很常见)方法strtok_r是使用预处理器:

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

As the prototypes and functionality is the same, you can now use only strtok_r.

由于原型和功能相同,您现在只能使用strtok_r.

回答by BeReal82

I don't have enough reputation to comment on other answers, so I'll have to provide my own.

我没有足够的声誉来评论其他答案,所以我必须提供我自己的。

1) To address this statement:

1) 要解决此声明:

"strtok_s is a buffer overrun safe version of strtok on Windows. The standard strtok on windows is thread safe..."

“strtok_s 是 Windows 上 strtok 的缓冲区溢出安全版本。Windows 上的标准 strtok 是线程安全的......”

This is not true. strtok_s is the thread safe version for the MSVC compiler. strtok is not thread safe!

这不是真的。strtok_s 是 MSVC 编译器的线程安全版本。strtok 不是线程安全的!

2) To address this statement:

2) 要解决此声明:

"This would probably break if compiling on Cygwin which reports itself as windows but has POSIX interfaces like strtok_ralready defined."

“如果在 Cygwin 上编译,这可能会中断,Cygwin 将自身报告为 Windows,但具有strtok_r已定义的POSIX 接口。”

Again, not true. The difference is which compiler you use. When using Microsoft's Visual C++ compiler, MSVC, the function is strtok_s.Another compiler, such as the GNU Compiler Collection, GCC, may use a different standard library implementation such as strtok_r. Think compiler, not target platform, when identifying which function to use.

再次,不是真的。不同之处在于您使用的编译器。当使用微软的 Visual C++ 编译器 MSVC 时,函数是strtok_s.另一个编译器,例如 GNU Compiler Collection,GCC,可能会使用不同的标准库实现,例如strtok_r. 在确定要使用的函数时,请考虑编译器,而不是目标平台。

In my opinion, Joachim Pileborg's answer is the best one on this page. However, it needs a small edit:

在我看来,Joachim Pileborg 的回答是这一页上最好的回答。但是,它需要一个小的编辑:

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

Both _WIN32 and _WIN64 are predefined macros provided by the MSVC compiler. _WIN64 is defined when compiling a 64 bit target. _WIN32 is defined for both 32 and 64 bit targets. This is a compromise that Microsoft made for backwards compatibility. _WIN32 was created to specify the Win32 API. Now you should consider _WIN32 to specify Windows API -- it is not specific to a 32 bit target.

_WIN32 和 _WIN64 都是 MSVC 编译器提供的预定义宏。_WIN64 在编译 64 位目标时定义。_WIN32 是为 32 位和 64 位目标定义的。这是 Microsoft 为向后兼容性所做的妥协。_WIN32 被创建来指定 Win32 API。现在您应该考虑使用 _WIN32 来指定 Windows API——它不是特定于 32 位目标。

回答by Jamey Kirby

Just to clarify. strtokis thread safe in Windows. strtokuses a TLSvariable to maintain the last pointer for each thread. However, you can not use strtokto interleave access to more than one token string per thread. strtok_rand strtok_sboth address this interleaving problem by allowing the user to maintain the context via the third parameter. Hope this helps.

只是为了澄清。strtok在 Windows 中是线程安全的。strtok使用一个TLS变量来维护每个线程的最后一个指针。但是,您不能使用strtok交错访问每个线程多个令牌字符串。strtok_r并且strtok_s两者都通过允许用户通过第三个参数维护上下文来解决这个交织问题。希望这可以帮助。

回答by Victor

MinGW also predefines _WIN32but it supports strtok_r, so I don't think it is a good idea to check the _WIN32macro. It is better to check the _MSC_VERmacro, which is the macro for Microsoft Visual Studio.

MinGW 也预定义_WIN32但它支持strtok_r,所以我认为检查_WIN32宏不是一个好主意。最好检查一下_MSC_VER宏,这是Microsoft Visual Studio 的宏。

#ifdef _MSC_VER
#define strtok_r strtok_s
#endif

WARNING: Microsoft strtok_sand C11 strtok_sare completely different! Microsoft strtok_shas only 3 parameters, while C11 strtok_shas 4 parameters, so it can be a compatible issue in the future.

警告:Microsoftstrtok_s和 C11strtok_s完全不同!微软strtok_s只有3个参数,而C11strtok_s有4个参数,所以以后可能会是兼容问题。

The prototype of Microsoft strtok_sis

微软的原型strtok_s

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

The prototype of C11 strtok_sis

C11的原型strtok_s

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