【问题标题】:C strndup implicit declarationC strndup 隐式声明
【发布时间】:2017-09-02 11:40:23
【问题描述】:

我正在尝试使用strndup 函数,但出现错误

错误:函数“strndup”的隐式声明 [-Werror=隐式函数声明]

我四处搜索,发现它不是标准函数,因此我必须使用不同的标志进行编译。但是,我通过编译以下内容收到了同样的问题:

-std=gnu11
-Wall
-Wextra
-Werror
-Wmissing-declarations
-Wmissing-prototypes
-Werror-implicit-function-declaration
-Wreturn-type
-Wparentheses
-Wunused
-Wold-style-definition
-Wundef
-Wshadow
-Wstrict-prototypes
-Wswitch-default
-Wunreachable-code
-D_GNU_SOURCE

我正在做一个作业,因此我必须使用所有这些,但我发现我必须使用 '-D_GNU_SOURCE' 进行编译才能让错误消失,但事实并非如此。

编辑:

我也有这些:

#define __STDC_WANT_LIB_EXT2__ 1
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "list.h"

非常感谢帮助解决此问题。

【问题讨论】:

标签: c


【解决方案1】:

函数 strdupstrndup 还不是标准 C 的一部分。它们在 Posix.1-2008 中标准化,并在 Posix 系统上的 &lt;string.h&gt; 中声明。是否包含&lt;string.h&gt;

如果您的系统不提供这些功能,您可以这样定义:

#include <string.h>
#include <stdlib.h>

char *strdup(const char *s) {
    size_t size = strlen(s) + 1;
    char *p = malloc(size);
    if (p != NULL) {
        memcpy(p, s, size);
    }
    return p;
}

char *strndup(const char *s, size_t n) {
    char *p;
    size_t n1;

    for (n1 = 0; n1 < n && s[n1] != '\0'; n1++)
        continue;
    p = malloc(n + 1);
    if (p != NULL) {
        memcpy(p, s, n1);
        p[n1] = '\0';
    }
    return p;
}

【讨论】:

  • 您的 strndup 函数与 PeterJ_01 上面发布的函数相比的主要区别是什么?
  • @Cows42:PeterJ_01 发布的版本没有实现 Posix 中指定的strndup() 的精确语义(参见linux.die.net/man/3/strndup
  • 好的,我在我的程序中使用你的实现可以吗?
  • @Cows42:当然!我在 SO 上发布的所有代码都放入公共域。
  • @chqrlie 抱歉 - 试图摆脱真正无聊的工作
【解决方案2】:

请求 POSIX 函数

您可能会发现您可以通过设置适当的宏来“激活”strndup() 等人的声明以请求 POSIX 支持:

#define _XOPEN_SOURCE 700

这严格来说是针对 X/Open SU​​S(单一 Unix 规范)的,但这通常是您想要的。严格只启用 POSIX 功能需要:

#define _POSIX_C_SOURCE 200809L

-std=gnu11 编译器选项通常默认启用所有这些(以及其他特殊选项),因此您遇到问题的事实表明您可能无论如何都没有可用的功能。

如果您没有strndup() 可用,即使在包含任何标题之前设置了启用宏,您可以编写自己的函数版本。棘手的部分是使声明在合适的标题中可用。但是,作为创可贴,您可以在唯一需要它的源文件中将其设为 static。如果您有strnlen() 可用,它也最容易实现。如果您也没有strnlen()(一个似是而非的问题),那么您也需要编写它,但是纯 C 版本可能无法与 strnlen() 的汇编版本的速度相匹配——或者使用 memchr() .

strndup()

char *strndup(const char *str, size_t len)
{
    size_t act = strnlen(str, len);
    char *dst = malloc(act + 1);
    if (dst != 0)
    {
        memmove(dst, str, act);
        dst[act] = '\0';
    }
    return dst;
}

(我注意到chqrlie shows 是使用memchr() 而不是strnlen() 的简洁替代方案。)

strnlen()

size_t strnlen(const char *str, size_t len)
{
    for (size_t size = 0; size < len; size++)
    {
        if (str[size] == '\0')
            return size;
    }
    return len;
}

【讨论】:

  • 请注意:使用 Codeblocks (17.12),必须将 -std=gnu11 选项放入编译器配置命令行中。 (其他编译器选项)与选择C11作为标准的复选框冲突。
【解决方案3】:

在不知道你的代码的情况下,我猜你忘了包含string.h

#include <string.h> 

如果您不包含特定标头,则函数 strndup() 的声明对编译器不可见。因此没有声明strndup() 的错误消息。

将上述行放在代码的顶部,它应该可以工作。

【讨论】:

  • 对不起,我忘记在主帖中包含这个了。但我的代码中已经有了这个:#define STDC_WANT_LIB_EXT2 1 #include #include #include #include "list.h"跨度>
  • 你的构建环境是什么。头文件是否存在?
  • 我使用 Codelite,如果您要问的话,我已经安装了 gcc 编译器。头文件都存在,因为其他功能工作正常。
【解决方案4】:

strdup & strndup 不是 C 标准的一部分。它们是 POSIX 函数。因此,您的库中可能没有它们。

char *mystrndup(const char *src, size_t size)
{
    char *duplicate = NULL;
    size_t len;

    if (src != NULL ) //for @chqrlie
    {
        len = strlen(src);
        size = len > (size) ? size + 1 : (size = len + 1))
        duplicate = calloc(sizeof(char), size);

        if (duplicate != NULL)
        {
            strncpy(duplicate, src, size - 1);
        }
        else
        {
            errno = ENOMEM;
        }
    } 
    else
    {
        errno = EINVAL;
    }
    return duplicate;
}

【讨论】:

  • 那我该如何让它工作呢?我也用我的代码中包含的内容更新了主帖子。
  • 如果你没有,你需要写一个。
  • strdup() 等。确实是 POSIX,并在 glibc 中得到支持;但似乎 OP 使用的是 Windows,对 POSIX 的支持总是值得怀疑的......
  • Posix: strndup() 函数应该等同于strdup() 函数,将提供的 s 复制到一个新分配的内存块中,就像使用 malloc() 一样,除了因为strndup() 最多将size 加上一个字节复制到新分配的内存中,以NUL 字符终止新字符串。如果s 的长度大于size,则只需要复制size 字节。如果size大于s的长度,则s中的所有字节都应复制到新的内存缓冲区中,包括终止NUL字符。
  • 请注意,标准库函数不会将errno 设置为零。
猜你喜欢
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 2012-02-29
  • 2016-08-10
  • 1970-01-01
相关资源
最近更新 更多