Reputation:
The source code.
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char **argv)
{
printf("Hello,Linux.\n");
exit(0);
}
To compile it with gcc.
gcc -o hello hello.c
To run it with 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
For the statement #include<stdio.h>
, Which file ,/usr/include/stdio.h
or/usr/include/x86_64-linux-gnu/bits/stdio.h
, used ?
The 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
Upvotes: 1
Views: 1404
Reputation: 753695
You misused the -H
option — you supplied it as the output file name for the -o
option. When you use gcc -o -H hello hello.c
, that attempts to create an output file ./-H
from the binary hello
and the result of compiling hello.c
. You need: 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
$
This is compiling your code on a Mac running macOS Sierra 10.12.5 using GCC 7.1.0. The list will be similar in spirit but radically different in detail on a Linux machine.
The number of leading dots tells you about the nested inclusion level.
The output from gcc -H
is written on stderr
, not stdout
. If you want to capture it, therefore (assuming a POSIX-like shell such as Bash or Korn shell), you'd use:
$ gcc -H -o hello hello.c 2>header.info
$
Upvotes: 2
Reputation: 17169
The short answer is: /usr/include/stdio.h
The correct answer is: more than one of them
The solution depends on the following premises:
INCLUDE
directory list. You can use the command cpp -v
to print the search list (Assuming cpp
is your preprocessor, which is likely true. Determining which preprocessor is being used just adds another level of indirection)On my SUSE linux system I get the following output
$ 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
contains the following code
/* 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
That means that after reading in the file the preprocessor also reads in /usr/include/bits/stdio.h
if __USE_EXTERN_INLINES
is defined.
bits/stdio.h
is supplementary. When you look inside the file you will notice that it starts with a warning message straight after the license text:#ifndef _STDIO_H # error "Never include <bits/stdio.h> directly; use <stdio.h> instead." #endif
That is this file is to be included only via the proper /usr/include/stdio.h
file
Upvotes: 1
Reputation: 4044
If you compile just with -E it will give you preprocessed output for hello.c, it will include path for header files that were expanded during preprocessing, you can see which stdio.h is used there
Upvotes: 2