简体   繁体   English

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

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

I'm trying to use this function in a C program that needs to be able to compile in Linux and Windows.我正在尝试在需要能够在 Linux 和 Windows 中编译的 C 程序中使用此函数。 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.起初我尝试使用 strtok_r,但是当我在 Windows 上编译时,它抱怨该函数不存在并说它会假设它是一个外部函数,但后来失败了。 I then used strtok_s and it compiled!然后我使用 strtok_s 并编译! Then I tried on Linux but now it's complaining that there is an "undefined reference to 'strtok_s'".然后我在 Linux 上尝试,但现在它抱怨有一个“对'strtok_s'的未定义引用”。

Is one a windows only function and the other a linux function???一个是windows唯一的函数,另一个是linux函数??? What can I do to make it compile on both?我该怎么做才能让它在两者上编译?

strtok_s is simply the Windows version of strtok_r which 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_r is 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

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_s 是 MSVC 编译器的线程安全版本。 strtok is not thread safe! 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_r already 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.使用 Microsoft 的 Visual C++ 编译器 MSVC 时,函数为strtok_s. Another compiler, such as the GNU Compiler Collection, GCC, may use a different standard library implementation such as strtok_r .另一个编译器,例如 GNU Compiler Collection, GCC,可能使用不同的标准库实现,例如strtok_r Think compiler, not target platform, when identifying which function to use.在确定要使用的函数时,请考虑编译器,而不是目标平台。

In my opinion, Joachim Pileborg's answer is the best one on this page.在我看来,Joachim Pileborg 的回答是这一页上最好的回答。 However, it needs a small edit:但是,它需要一个小的编辑:

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

Both _WIN32 and _WIN64 are predefined macros provided by the MSVC compiler. _WIN32 和 _WIN64 都是 MSVC 编译器提供的预定义宏。 _WIN64 is defined when compiling a 64 bit target. _WIN64 在编译 64 位目标时定义。 _WIN32 is defined for both 32 and 64 bit targets. _WIN32 是为 32 位和 64 位目标定义的。 This is a compromise that Microsoft made for backwards compatibility.这是 Microsoft 为向后兼容性所做的妥协。 _WIN32 was created to specify the Win32 API. _WIN32 被创建来指定 Win32 API。 Now you should consider _WIN32 to specify Windows API -- it is not specific to a 32 bit target.现在您应该考虑使用 _WIN32 来指定 Windows API——它不是特定于 32 位目标。

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 strtok in standard C. Just throw them out and write your own code to iterate over the char array and break it up as needed.对于标准 C 中的普通strtok 。只需将它们扔掉并编写您自己的代码来迭代char数组并根据需要将其分解。 strchr , strspn , and strcspn can be helpful in doing this or you can just work from scratch on the array. strchrstrspnstrcspn可以帮助执行此操作,或者您可以从头开始处理数组。

Just to clarify.只是为了澄清。 strtok is thread safe in Windows. strtok在 Windows 中是线程安全的。 strtok uses a TLS variable to maintain the last pointer for each thread. strtok使用TLS变量来维护每个线程的最后一个指针。 However, you can not use strtok to interleave access to more than one token string per thread.但是,您不能使用strtok对每个线程的多个令牌字符串进行交错访问。 strtok_r and strtok_s both address this interleaving problem by allowing the user to maintain the context via the third parameter. strtok_rstrtok_s都通过允许用户通过第三个参数维护上下文来解决这个交织问题。 Hope this helps.希望这可以帮助。

strtok_r is a thread safe version of strtok on POSIX systems strtok_r 是 POSIX 系统上 strtok 的线程安全版本

strtok_s is a buffer overrun safe version of strtok on Windows. strtok_s是 Windows 上 strtok 的缓冲区溢出安全版本。 The standard strtok on windows is thread safe, so strtok_s should be. Windows 上的标准 strtok 是线程安全的,所以 strtok_s 应该是。

MinGW also predefines _WIN32 but it supports strtok_r , so I don't think it is a good idea to check the _WIN32 macro. MinGW 也预定义了_WIN32但它支持strtok_r ,所以我认为检查_WIN32宏不是一个好主意。 It is better to check the _MSC_VER macro, which is the macro for Microsoft Visual Studio.最好检查_MSC_VER宏,这是Microsoft Visual Studio 的宏。

#ifdef _MSC_VER
#define strtok_r strtok_s
#endif

WARNING: Microsoft strtok_s and C11 strtok_s are completely different!警告:Microsoft strtok_s和 C11 strtok_s完全不同! Microsoft strtok_s has only 3 parameters, while C11 strtok_s has 4 parameters, so it can be a compatible issue in the future.微软的strtok_s只有3个参数,而C11 strtok_s有4个参数,所以以后可能会出现兼容问题。

The prototype of Microsoft strtok_s is微软strtok_s的原型是

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

The prototype of C11 strtok_s is 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