strdup()函数

时间:2009-01-27 05:14:57

标签: c strdup

我最近意识到我在OS X上使用的strdup()函数不是ANSI C的一部分,而是POSIX的一部分。我不想重写我的所有代码,所以我想我只是要编写自己的strdup()函数。这并不难,真的,它只是malloc()strcpy()。无论如何,我有这个功能,但是如果我编写这个函数并将其链接到我的代码,我该怎么做,它已经存在于libc中了?我的链接器或编译器是否允许我基本上定义我自己的函数版本,还是我必须给它另一个名字?如果有一种方法可以重用相同的名称,那将非常方便,因此如果用户的libc中存在strcpy(),他们可以使用它,但如果它们的libc中不存在,则可以使用我的版本代替,尽可能少改变代码。

简短版本:

a)当我使用与内置函数相同的名称编写自己的函数时会发生什么?

b)我可以做些什么来避免在没有strdup()的平台上发生错误的事情而不重写我的所有代码而不使用strdup(),这有点单调乏味?< / p>

7 个答案:

答案 0 :(得分:20)

通常,您只需使用#if在某个编译器下定义所需的函数。如果内置库没有定义strdup,那么自己定义它是没有问题的(除非他们将来定义它,否则你必须把它拿出来。)

// Only define strdup for platforms that are missing it..
#if COMPILER_XYZ || COMPILER_ABC
char *strdup(const char *)
{
   // ....
}
#endif

答案 1 :(得分:6)

你可以使用像这样的宏,这样你就可以使用旧名称,但链接器会看到不同的名称;

char *my_strdup(const char *s) {
    char *p = malloc(strlen(s) + 1);
    if(p) { strcpy(p, s); }
    return p;
}

/* this goes in whatever header defines my_strdup */
char *my_strdup(const char *s);
#define strdup(x) my_strdup(x)

答案 2 :(得分:6)

正如Rob Kennedy所指出的,如果这个功能存在与否,最好的方法是在你的建筑脚本中进行测试。我知道autoconfig相当容易,但也可能使用其他跨平台构建脚本工具。

然后您只需将其放在头文件中:


#ifndef HAVE_STRDUP
# ifdef HAVE__STRDUP
#  define strdup _strdup
# else
#  define strdup my_strdup
# endif
#endif

如果目标平台上已存在strdup,则使用libc版本,否则将使用自定义my_strdup函数。

编辑:我应该添加一个探索为什么它更好。

首先,编译器与libc中存在的函数无关。例如,使用函数strlcpy。它存在于FreeBSD上但不存在于Linux(glibc)上,尽管两者都默认使用gcc。或者如果有人要用clang编译你的代码会发生什么?

第二个平台检查(我不知道是否有标准方法)只有在你想要支持正确的预处理器条件的每个平台上显式添加时才会起作用。因此,假设您已经掌握了在OSX和Win32上编译应用程序并且您希望现在在Linux上编译它,您将必须通过所有预处理器条件来查看它们是否适用于Linux。也许你也想支持FreeBSD,OpenBSD等?同样的工作。通过在构建脚本中进行测试,它可以在没有任何额外工作的情况下进行编译。

答案 3 :(得分:4)

  

a)当我写自己的时候会发生什么   与a同名的函数   内置功能?

您无法重新定义已包含的头文件中已存在的函数。这将导致编译错误。

  b)我能做些什么来避免坏事   发生在我的平台上   没有重写就没有strdup()   我的所有代码都不使用strdup(),哪个   有点单调乏味吗?

我建议您创建自己的包装函数来进行strdup,并替换所有调用以使用新的包装函数。例如:

char *StringDuplicate(const char *s1)
{
#ifdef POSIX
    return strdup(s1);
#else
    /* Insert your own code here */
#endif
}

将所有调用从strdup更改为StringDuplicate()应该是一个简单的查找和替换操作,使其成为一种可行的方法。然后,特定于平台的逻辑将保存在一个位置,而不是分散在整个代码库中。

答案 4 :(得分:3)

您还应该考虑避免创建以str [a-z]开头的任何标识符(包括函数)。虽然这不是保留,但C标准(ISO / IEC 9899:1999)第7.26.11节(未来的库指示)声明“可以将以str,mem或wcs开头的函数名称和小写字母添加到声明中在标题中。“

答案 5 :(得分:2)

仅供参考:我从未亲眼见过没有定义strdup()的环境。

答案 6 :(得分:-2)

如果有人读到这个:即使可用,也不要使用平台的strdup(),并且不要浪费时间/精力使用autoconf / automake来使用它。说真的,这有多难:

char* mystrdup(const char* str)
{
 return strcpy(malloc( strlen(str) + 1),str);
}

这真的值得#ifdefs吗?编译检查? K.I.S.S。