user7988893
user7988893

Reputation:

Which stdio.h was included for the hello.c?

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

Answers (3)

Jonathan Leffler
Jonathan Leffler

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

Dima Chubarov
Dima Chubarov

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:

  1. The search for C preprocessor include files is guided by the 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.
  1. Header files often include other header files.

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.

  1. The 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

Pras
Pras

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

Related Questions