Clang 无法编译 c11 程序,引用 "implicit declaration is illegal in c99"

Clang fails to compile a c11 program, citing that "implicit declaration is illegal in c99"

我写了这个简单的小程序来演示我的问题(标题为 hello.c)(旁注:我注意到这个程序中的内存泄漏,但这只是一个例子,所以它并不重要):

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv) {
    char * buf = NULL;
    size_t buflen = 0;

    ssize_t line_len;

    while ((line_len = getline(&buf, &buflen, stdin)) > 0) {
        buf[line_len - 1] = '[=11=]';

        char * val = getenv(buf);

        if (val) {
            printf("setenv %s \"%s\"\n", buf, val);
        }
        else {
            fprintf(stderr, "warning: %s not found\n", buf);
        }
    }

    return EXIT_SUCCESS;
}

这在 Linux 下编译良好,使用 gcc 和 gnu make 以及以下 makefile:

CFLAGS += -std=c11 -Wall -Werror -Wpedantic
CPPFLAGS := -D_XOPEN_SOURCE=700

EXES := hello

all: $(EXES)

clean:
    rm -f $(EXES) *.o

然而,在 BSD 下,使用 clang 和 bmake,我无法编译(使用完全相同的 makefile 和源文件),因为它说

hello.c:11:24: error: implicit declaration of function 'getline' is invalid in
  C99 [-Werror,-Wimplicit-function-declaration]

问题是,如您所见,我不是 在 c99 模式下编译,而是在 c11 下编译,而且,根据手册页定义 _POSIX_C_SOURCE 为 200809 或更高应该启用 getline,在其他地方我确信将 _XOPEN_SOURCE 定义为 700 应该可以实现这一点。

去掉 -W 标志没有帮助。

那么,我做错了什么?我怎样才能让它编译?我被难住了。

您已设置 -std=c11 -Wpedantic,这意味着正常定义不可用且 POSIX 函数不会声明,除非您显式设置 _POSIX_C_SOURCE 或 [=13] 之一=].在第一个 #include 之前添加 #define _XOPEN_SOURCE 700(甚至 Linux 上的 800),一切都会好起来的。

您在 makefile 中有 CPPFLAGS = -D_XOPEN_SOURCE=700CPPFLAGS 是否实际显示在 GCC 命令行上?

我经常在 Mac OS X 10.10.1 上用 -std=c11 编译,我有一个 header 将 _XOPEN_SOURCE 设置为 700。但是,我可以使用你的代码并逐字编译它:

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Wold-style-definition -Werror -pedantic -c yourprog.c

唯一的抱怨是argcargv都没有被使用(所以编译确实失败了,但不是因为getline())。

注意 CPPFLAGS 不一定被 BSD make 识别。没有要求 CPPFLAGS 被识别的通用标准。