源代码。
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char **argv)
{
printf("Hello,Linux.\n");
exit(0);
}
用gcc编译它。
gcc -o hello hello.c
使用hello
运行它。
sudo find / -name 'stdio.h'
/usr/include/stdio.h
/usr/include/x86_64-linux-gnu/bits/stdio.h
/usr/include/c++/4.9/tr1/stdio.h
对于语句#include<stdio.h>
,使用了哪个文件/usr/include/stdio.h
或/usr/include/x86_64-linux-gnu/bits/stdio.h
?
os:
uname -a
Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64 GNU/Linux
gcc -o -H hello hello.c
hello: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
hello: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
hello: In function `data_start':
(.data+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o:(.data+0x0): first defined here
hello:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
hello: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
hello: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here
/tmp/ccNhnGzH.o: In function `main':
hello.c:(.text+0x0): multiple definition of `main'
hello:(.text+0xf6): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
hello:(.data+0x10): first defined here
/usr/bin/ld: error in hello(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
gcc -H -o hello hello.c
. /usr/include/stdio.h
.. /usr/include/features.h
... /usr/include/x86_64-linux-gnu/sys/cdefs.h
.... /usr/include/x86_64-linux-gnu/bits/wordsize.h
... /usr/include/x86_64-linux-gnu/gnu/stubs.h
.... /usr/include/x86_64-linux-gnu/gnu/stubs-64.h
.. /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h
.. /usr/include/x86_64-linux-gnu/bits/types.h
... /usr/include/x86_64-linux-gnu/bits/wordsize.h
... /usr/include/x86_64-linux-gnu/bits/typesizes.h
.. /usr/include/libio.h
... /usr/include/_G_config.h
.... /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h
.... /usr/include/wchar.h
... /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdarg.h
.. /usr/include/x86_64-linux-gnu/bits/stdio_lim.h
.. /usr/include/x86_64-linux-gnu/bits/sys_errlist.h
. /usr/include/stdlib.h
.. /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h
.. /usr/include/x86_64-linux-gnu/bits/waitflags.h
.. /usr/include/x86_64-linux-gnu/bits/waitstatus.h
... /usr/include/endian.h
.... /usr/include/x86_64-linux-gnu/bits/endian.h
.... /usr/include/x86_64-linux-gnu/bits/byteswap.h
..... /usr/include/x86_64-linux-gnu/bits/wordsize.h
..... /usr/include/x86_64-linux-gnu/bits/byteswap-16.h
.. /usr/include/x86_64-linux-gnu/sys/types.h
... /usr/include/time.h
... /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h
... /usr/include/x86_64-linux-gnu/sys/select.h
.... /usr/include/x86_64-linux-gnu/bits/select.h
..... /usr/include/x86_64-linux-gnu/bits/wordsize.h
.... /usr/include/x86_64-linux-gnu/bits/sigset.h
.... /usr/include/time.h
.... /usr/include/x86_64-linux-gnu/bits/time.h
... /usr/include/x86_64-linux-gnu/sys/sysmacros.h
... /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h
.... /usr/include/x86_64-linux-gnu/bits/wordsize.h
.. /usr/include/alloca.h
... /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stddef.h
.. /usr/include/x86_64-linux-gnu/bits/stdlib-float.h
Multiple include guards may be useful for:
/usr/include/wchar.h
/usr/include/x86_64-linux-gnu/bits/byteswap-16.h
/usr/include/x86_64-linux-gnu/bits/byteswap.h
/usr/include/x86_64-linux-gnu/bits/endian.h
/usr/include/x86_64-linux-gnu/bits/select.h
/usr/include/x86_64-linux-gnu/bits/sigset.h
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h
/usr/include/x86_64-linux-gnu/bits/stdlib-float.h
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h
/usr/include/x86_64-linux-gnu/bits/time.h
/usr/include/x86_64-linux-gnu/bits/typesizes.h
/usr/include/x86_64-linux-gnu/bits/waitflags.h
/usr/include/x86_64-linux-gnu/bits/waitstatus.h
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
/usr/include/x86_64-linux-gnu/gnu/stubs.h
答案 0 :(得分:3)
您误用了-H
选项 - 您将其作为-o
选项的输出文件名提供。当您使用gcc -o -H hello hello.c
时,会尝试从二进制文件./-H
创建输出文件hello
以及编译hello.c
的结果。您需要:gcc -H -o hello hello.c
!
$ gcc -H -o hello hello.c
. /usr/include/stdio.h
.. /usr/include/sys/cdefs.h
... /usr/include/sys/_symbol_aliasing.h
... /usr/include/sys/_posix_availability.h
.. /usr/include/Availability.h
... /opt/gcc/v7.1.0/lib/gcc/x86_64-apple-darwin16.5.0/7.1.0/include-fixed/AvailabilityInternal.h
.. /usr/include/_types.h
... /usr/include/sys/_types.h
.... /usr/include/machine/_types.h
..... /usr/include/i386/_types.h
.... /usr/include/sys/_pthread/_pthread_types.h
.. /usr/include/sys/_types/_va_list.h
.. /usr/include/sys/_types/_size_t.h
.. /usr/include/sys/_types/_null.h
.. /usr/include/sys/stdio.h
.. /usr/include/sys/_types/_off_t.h
.. /usr/include/sys/_types/_ssize_t.h
.. /usr/include/secure/_stdio.h
... /usr/include/secure/_common.h
. /usr/include/stdlib.h
.. /usr/include/sys/wait.h
... /usr/include/sys/_types/_pid_t.h
... /usr/include/sys/_types/_id_t.h
... /usr/include/sys/signal.h
.... /usr/include/sys/appleapiopts.h
.... /usr/include/machine/signal.h
..... /usr/include/i386/signal.h
.... /usr/include/machine/_mcontext.h
..... /usr/include/i386/_mcontext.h
...... /usr/include/mach/i386/_structs.h
.... /usr/include/sys/_pthread/_pthread_attr_t.h
.... /usr/include/sys/_types/_sigaltstack.h
.... /usr/include/sys/_types/_ucontext.h
.... /usr/include/sys/_types/_sigset_t.h
.... /usr/include/sys/_types/_uid_t.h
... /usr/include/sys/resource.h
.... /opt/gcc/v7.1.0/lib/gcc/x86_64-apple-darwin16.5.0/7.1.0/include/stdint.h
..... /opt/gcc/v7.1.0/lib/gcc/x86_64-apple-darwin16.5.0/7.1.0/include-fixed/stdint.h
...... /usr/include/sys/_types/_int8_t.h
...... /usr/include/sys/_types/_int16_t.h
...... /usr/include/sys/_types/_int32_t.h
...... /usr/include/sys/_types/_int64_t.h
...... /usr/include/_types/_uint8_t.h
...... /usr/include/_types/_uint16_t.h
...... /usr/include/_types/_uint32_t.h
...... /usr/include/_types/_uint64_t.h
...... /usr/include/sys/_types/_intptr_t.h
...... /usr/include/sys/_types/_uintptr_t.h
...... /usr/include/_types/_intmax_t.h
...... /usr/include/_types/_uintmax_t.h
.... /usr/include/sys/_types/_timeval.h
... /usr/include/machine/endian.h
.... /usr/include/i386/endian.h
..... /usr/include/sys/_endian.h
...... /usr/include/libkern/_OSByteOrder.h
....... /usr/include/libkern/i386/_OSByteOrder.h
.. /usr/include/alloca.h
.. /usr/include/sys/_types/_ct_rune_t.h
.. /usr/include/sys/_types/_rune_t.h
.. /usr/include/sys/_types/_wchar_t.h
.. /usr/include/machine/types.h
... /usr/include/i386/types.h
.... /usr/include/sys/_types/_u_int8_t.h
.... /usr/include/sys/_types/_u_int16_t.h
.... /usr/include/sys/_types/_u_int32_t.h
.... /usr/include/sys/_types/_u_int64_t.h
.. /usr/include/sys/_types/_dev_t.h
.. /usr/include/sys/_types/_mode_t.h
Multiple include guards may be useful for:
/usr/include/machine/_mcontext.h
/usr/include/secure/_stdio.h
/usr/include/sys/_posix_availability.h
/usr/include/sys/_symbol_aliasing.h
$
这是使用GCC 7.1.0在运行macOS Sierra 10.12.5的Mac上编译代码。该列表在精神上类似,但在Linux机器上的细节完全不同。
引导点的数量告诉您嵌套的包含级别。
gcc -H
的输出写在stderr
上,而不是stdout
。因此,如果你想捕获它(假设像Bash或Korn shell这样的类似POSIX的shell),你可以使用:
$ gcc -H -o hello hello.c 2>header.info
$
答案 1 :(得分:2)
简短的回答是:/usr/include/stdio.h
正确答案是:不止一个
解决方案取决于以下前提:
INCLUDE
目录列表引导。您可以使用命令cpp -v
来打印搜索列表(假设cpp
是您的预处理器,这可能是真的。确定正在使用哪个预处理器只会增加另一个间接级别 )在我的SUSE linux系统上,我得到以下输出
$ cpp -v
...
#include "..." search starts here:
#include <...> search starts here:
/usr/lib64/gcc/x86_64-suse-linux/4.8/include
/usr/local/include
/usr/lib64/gcc/x86_64-suse-linux/4.8/include-fixed
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/include
/usr/include
End of search list.
E.g。 /usr/include/stdio.h
包含以下代码
/* If we are compiling with optimizing read this file. It contains
several optimizing inline functions and macros. */
#ifdef __USE_EXTERN_INLINES
# include <bits/stdio.h>
#endif
这意味着在读取文件后,如果定义了/usr/include/bits/stdio.h
,预处理器也会读入__USE_EXTERN_INLINES
。
bits/stdio.h
是补充。当您查看文件内部时,您会注意到它在许可证文本之后直接显示警告消息:#ifndef _STDIO_H # error "Never include <bits/stdio.h> directly; use <stdio.h> instead." #endif
这个文件只能通过正确的/usr/include/stdio.h
文件
答案 2 :(得分:2)
如果只使用-E进行编译,它将为hello.c提供预处理输出,它将包含在预处理期间展开的头文件的路径,您可以看到在那里使用了哪个stdio.h