strdup还是_strdup?

71
当我在Microsoft Visual C++中使用strdup时,会出现警告:

警告 C4996:'strdup':此项的POSIX名称已弃用。请改用符合ISO C++标准的名称:_strdup。有关详细信息,请参见在线帮助。

因此,似乎_strdup是正确的。
但是,当我在GCC(Fedora Linux操作系统)中使用_strdup时,编译器会显示错误:

错误:在此范围内未声明“_strdup”

使用GCC和Linux时,编译器对strdup不会显示任何错误。
哪个是正确的-strdup还是_strdup
注意:我在我的代码中包含了<string.h>

4
在 C++ 中,考虑使用 std::string 而不是 C 风格的字符串,问题就会消失。此外,在 C++ 中,头文件只需使用 <cstring> - johnsyweb
1
@Rowland Shaw:我的意思是GCC在“_strdup”上显示错误,但对“strdup”没有显示任何错误。我的测试平台是Fedora Linux。 - Amir Saniyan
1
请注意,在 Visual Studio 2013 及以后的版本中,这些警告现在已经变成了错误。 - jrh
7个回答

47
哪个是正确的? strdup 是一个完全正确的 POSIX 函数。然而,它不属于标准,并且 ANSI C 标准保留了一些(广义的)函数名称类别供进一步使用。其中包括:
  • str 和小写字母开头的函数名称
因此,微软的人们决定用 _strdup 替换 strdup
我会继续使用 strdup。C 委员会不太可能把 strdup 定义为与 POSIX 不同的内容。要么使用 #define strdup _strdup,要么忽略警告。
顺便说一句,希望您也应该注意具有类似 string_list 等名称的函数。

1
似乎与POSIX不同,ISO C在不久的将来可能永远不会定义strdup。请参见N1118中的“无隐式分配规则”。 - FrankHB
1
@FrankHB:永远不要说“永远”!strdup终于进入了下一个C标准:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf 但我猜你对“不久的将来”是正确的,在C世界中,10年很快。 - chqrlie
1
我已经意识到这个问题多年了。看到WG14打破他们的隐性规则很有趣。 - FrankHB
C2x可能会使用strdup(),但其功能与POSIX或MS的strdup()并不完全相同。 _strdup()是更好的选择。 - chux - Reinstate Monica
C2x很可能会使用strdup(),但其功能与POSIX和MS的strdup()并不完全相同。 _strdup()是更好的选择。 - chux - Reinstate Monica
显示剩余8条评论

35

strdup 不是标准的 C++ 函数。但它显然是 POSIX 函数,而且它是自从 K&R C 以来一直存在的 众所周知的函数。因此,如果你非常需要使用它,请不要担心任何可能的名称冲突,只需写 strdup 即可实现最大的可移植性。


5
问题在于,MSVC中有许多“符合POSIX标准的_foo”,这非常令人厌烦。如果你想要“安静编译”(尤其是对于大型项目),同时又可以将其移植到GCC,则会变得更加麻烦。例如_fileno、_isatty(当使用Flex解析器生成器时)以及许多其他系统函数。目前,我在#ifdef _MSC_VER内添加了许多#define,但我一直在寻找更好的解决方案。 - Tomasz Gandor
4
一种替代 #ifdef 的方法是通过编译器的头文件搜索路径使用特定于编译器的头文件选择。一种替代 #define 的方法(因为宏不尊重作用域)是使用“内联”转发函数。 - Cheers and hth. - Alf
23
只需使用“-D_CRT_NONSTDC_NO_DEPRECATE”。它应该可以在任何地方工作,并且对于MSVC,它将使其安静。它的唯一目的是在移植应用程序时惹恼用户。它还可能具有某些用例,其中MSVCRT变体的行为与POSIX / C99变体不同。目前我无法想到任何用例。 - Mark Nunberg
4
请仔细阅读文档中关于 _snprintf() 的内容。 - Zan Lynx
2
为了让事情更加疯狂,VS2015会产生这些“错误”,你必须使用多个非标准的#define才能恢复正常行为。 - Glenn Maynard
显示剩余11条评论

28

13

如果你只是想避免警告信息:

项目 -> 属性 -> C/C++ -> 预处理器 -> 预处理器定义

编辑此项,并添加

_CRT_NONSTDC_NO_DEPRECATE


9

strdup是POSIX标准:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html

_strdup是Windows特有的:

http://msdn.microsoft.com/en-us/library/y471khhc(v=vs.80).aspx

在Unix上使用strdup,在Windows上使用_strdup。就这么简单。如果需要在Unix和Windows之间编写可移植代码:

  • 使用系统相关宏(例如_WIN32 vs. _POSIX_VERSION)来选择正确的函数(但请注意,这些宏可能依赖于特定的预先存在的包含文件):

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html

http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.80).aspx

  • 使用标准函数重新实现strdup: strlen、malloc和memmove。

  • 使用跨平台实用程序库,例如glib:

http://developer.gnome.org/glib/2.28/glib-String-Utility-Functions.html#g-strdup

请注意,Visual C++消息表明_strdup属于C++标准,但这是错误的,可以在C++标准上验证。它只是使用下划线前缀作为函数的“命名空间”。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf


11
“MSVC”从未暗示“_strdup”属于C++标准!它只是说“_strdup”是符合C++标准的名称。正如您和其他人所说,strdup是由“POSIX”系统使用的保留名称,因此微软认为使用“_strdup”可以解决保留名称的问题。 - BigBoss

5

不了解C++。

C标准中没有描述任何名为strdup的函数(尽管该名称已被保留)。 为了可移植性,在C语言中,最好用mallocstrcpyfree替换它。


我同意这个观点。这个函数一直以来都是多余的。 - Lundin
我刚刚查看了(可能的)下一个C标准C2011?),它也没有描述strdup - pmg
2
@pmg:10年后,“strdup”终于进入了下一个C标准:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf 但我猜在C标准的世界里,10年很快。 - chqrlie

0

这不是警告,而是在较高版本的VS中报告的错误。

使用宏#ifdef WIN32进行切换。


1
就像在自己的答案上发表评论一样没有用。 - Owl
1
最好使用 #ifdef _MSC_VER 检查 Microsoft 编译器,因为在 WIN32 平台上可能会有 MINGW 或其他编译器。 - Alexander Ushakov
@AlexanderUshakov 是的 - yjjjnls

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接