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

时间:2012-01-26 16:29:34

标签: c windows linux compiler-errors strtok

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

是一个只有Windows的功能而另一个是linux功能吗?我该怎么做才能在两者上编译?

6 个答案:

答案 0 :(得分:31)

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

strtok_s / strtok_r这样的函数中,使程序可移植的一种(我会想到的)方法是使用预处理器:

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

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

答案 1 :(得分:9)

这两个函数都是用于解析字符串的非常丑陋,不直观的习惯用法,并且通常无法以微妙的方式满足您的特定应用程序的要求。对于标准C中的普通strtok,甚至更多。只需抛出它们并编写自己的代码来迭代char数组并根据需要将其分解。 strchrstrspnstrcspn可以帮助您做到这一点,或者您可以在数组上从头开始工作。

答案 2 :(得分:9)

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

要解决这个问题:

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

事实并非如此。 strtok_s是MSVC编译器的线程安全版本。 strtok不是线程安全的!

要解决这个问题:

“如果在cygwin上进行编译时可能会破坏,cygwin会将自己报告为窗口但是已经定义了strtok_r等posix接口。”

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

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

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

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

答案 3 :(得分:4)

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

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

答案 4 :(得分:4)

只是澄清一下。 strtok在Windows中是线程安全的。 strtok使用TLS变量来维护每个线程的最后一个指针。但是,您不能使用strtok来交错访问每个线程的多个标记字符串。 strtok_r和strtok_s都通过允许用户通过第三个参数维护上下文来解决这个交错问题。希望这会有所帮助。

答案 5 :(得分:0)

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);