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=700
; CPPFLAGS
是否实际显示在 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
唯一的抱怨是argc
和argv
都没有被使用(所以编译确实失败了,但不是因为getline()
)。
注意 CPPFLAGS
不一定被 BSD make
识别。没有要求 CPPFLAGS
被识别的通用标准。
我写了这个简单的小程序来演示我的问题(标题为 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=700
; CPPFLAGS
是否实际显示在 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
唯一的抱怨是argc
和argv
都没有被使用(所以编译确实失败了,但不是因为getline()
)。
注意 CPPFLAGS
不一定被 BSD make
识别。没有要求 CPPFLAGS
被识别的通用标准。