How does gcc handle local included files?

P...

This really shouldn't be something I have to ask, but somehow I can find absolutely nothing by searching to answer my question.

In order to ask another question, I made three files: main.c, sub.c and sub.h. main.c has the 'main' function, while sub.c contains only function definitions.

Initially, main.c had '#include "sub.h"' as its only include statement.

Trying 'gcc main.c -O3 -o test' resulted in an error, saying that the function f() (declared in sub.h, defined in sub.c, and referenced in main.c) was unreferenced. Trying 'gcc main.c sub.c -O3 -o test' resulted in expected behaviour.

I then modified test.c, removing the #include and references to f. 'gcc main.c -O3 -o test2' worked as expected.

I then re-added the references to f, and forgot to re-add the #include. Despite this, 'gcc main.c sub.c -O3 -o test3' worked as expected.

I noticed the mistake, and re-added the include intentionally as '#include sub.c'. 'gcc main.c sub.c -O3 -o test4' resulted in an error, saying f() was defined multiple times. 'gcc main.c -O3 -o test4 returned to working as expected.

The only conclusion I can draw from this is that as far as local files are concerned, if the file is a source code file then include it and don't add it to the command, else add its source to the command and don't bother including it, because apparently it doesn't matter whether you include it or not. I guess?

Basically my question is, is the behaviour above intended, and if so is it documented, and where, so I can read it and make better informed decisions about how to handle my included files in the future.

John Bode

I then re-added the references to f, and forgot to re-add the #include. Despite this, 'gcc main.c sub.c -O3 -o test3' worked as expected.

For suitably loose definitions of "worked"; I'm going to bet that f() returns an int, and that gcc was defaulting to C89 mode.

Prior to C99, if the compiler encountered a function call before it saw a function definition or declaration, it assumed that the called function returned an int. Thus, as long as f() actually returns an int, your code will compile and run successfully. If f() doesn't return an int the code will still compile, but you will have a runtime problem. All the linker cares about is that the symbol is there; it doesn't care about type mismatches.

C99 did away with implicit int typing, so under a C99 compiler your code would fail to compile if you didn't have a declaration for f() in scope (either by including sub.h or adding the declaration manually).

The only conclusion I can draw from this is that as far as local files are concerned, if the file is a source code file then include it and don't add it to the command, else add its source to the command and don't bother including it, because apparently it doesn't matter whether you include it or not. I guess?

That is the exact wrong conclusion to draw. You do not want to include a .c file within another .c file as a regular practice, as it can lead to all kinds of mayhem. Everything in main.c is visible to sub.c and vice versa, leading to potential namespace collisions - for example, both files could define a "local" helper function named foo(). Normally such "local" functions aren't visible outside of the source file, but by including one source file within the other, both versions of foo() are visible and clash with each other. Another problem is that if a .c file includes another .c file which includes another .c file, etc., you may wind up with a translation unit that's too large for the compiler to handle. You will wind up recompiling both files every time you change one or the other where it isn't necessary. It's just bad practice all the way around.

The right thing to do is compile main.c and sub.c separately and make sure sub.h is included in both (you want to include sub.h in sub.c to make sure your declarations line up with your definitions; if they don't, the compiler will yak while translating sub.c).

Edit

Answering the following question in the comments:

When you say to compile main.c and sub.c separately, I'm assuming you mean to make object files out of them each individually and then link them (3 commands total)? Is there any way to do that with a single command?

The command gcc -o test main.c sub.c does the same thing, it just doesn't save the respective object files to disk. You could also create a simple Makefile, like so:

CC=gcc
CFLAGS=-O3 -std=c99 -pedantic -Wall -Werror

SRCS=main.c sub.c
OBJS=$(SRCS:.c=.o)

test: $(OBJS)
        $(CC) -o $@ $(CFLAGS) $(OBJS)

clean:
        rm -rf test $(OBJS)

Then all you need to do is type make test:

[fbgo448@n9dvap997]~/prototypes/simplemake: make test
gcc -O3 -std=c99 -pedantic -Wall -Werror   -c -o main.o main.c
gcc -O3 -std=c99 -pedantic -Wall -Werror   -c -o sub.o sub.c
gcc -o test -O3 -std=c99 -pedantic -Wall -Werror main.o sub.o

There are implicit rules for building object files from .c files, so you don't need to include those rules in your Makefile. All you need to do is specify targets and prerequisites.

You may need to drop the -pedantic flag to use some platform-specific utilities, and you may need to specify a different standard (c89, gnu89, etc.) as well. You will definitely want to keep the -Wall -Werror flags, though - they'll enable all warnings and treat all warnings as errors; they'll force you to deal with warnings.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How does GCC handle variable redefinition

From Dev

How does gcc push local variables on to the stack?

From Dev

More verbose mode for included files in GCC

From Dev

How does "cp" handle open files?

From Dev

How does ssh handle 2 computers on the local network with the same username?

From Dev

How to handle if extra header file included?

From Dev

Flask app does not talk to included files

From Dev

How does webpack handle multiple files importing the same module React

From Dev

How does git handle moving files in the file system?

From Dev

How does numpy handle mmap's over npz files?

From Dev

GCC not finding header files in /usr/local/include

From Dev

How does a debugger like GDB handle code optimizations made by compilers like ICC/GCC?

From Dev

Handle local files in default iOS application

From Dev

how print an http request contents into a terminal as "cat" does to local files?

From Dev

How do I handle the Git error "Your local changes to the following files would be overwritten by merge"

From Dev

How do I handle the Git error "Your local changes to the following files would be overwritten by merge"

From Dev

How to read data files included in the app

From Dev

How to read data files included in the app

From Dev

How to use included Files in Executables Jar

From Dev

How to include a file in already included files in php?

From Dev

How to handle dual ABI in GCC 5?

From Dev

How to handle error compiling GCC 4.7.0 using GCC 6.2.1

From Dev

How to XHR local files?

From Dev

How to set PHPStorm to check for variable usage in required/included files? How to check variable definition in required/included files?

From Dev

Does PHP required or included files need to follow the order?

From Dev

Why does the executable binary file contain paths of included header files?

From Dev

Why does Visual Studio error when linking having files included?

From Dev

Does PHP required or included files need to follow the order?

From Dev

Does GCC merge files compiled together?

Related Related

  1. 1

    How does GCC handle variable redefinition

  2. 2

    How does gcc push local variables on to the stack?

  3. 3

    More verbose mode for included files in GCC

  4. 4

    How does "cp" handle open files?

  5. 5

    How does ssh handle 2 computers on the local network with the same username?

  6. 6

    How to handle if extra header file included?

  7. 7

    Flask app does not talk to included files

  8. 8

    How does webpack handle multiple files importing the same module React

  9. 9

    How does git handle moving files in the file system?

  10. 10

    How does numpy handle mmap's over npz files?

  11. 11

    GCC not finding header files in /usr/local/include

  12. 12

    How does a debugger like GDB handle code optimizations made by compilers like ICC/GCC?

  13. 13

    Handle local files in default iOS application

  14. 14

    how print an http request contents into a terminal as "cat" does to local files?

  15. 15

    How do I handle the Git error "Your local changes to the following files would be overwritten by merge"

  16. 16

    How do I handle the Git error "Your local changes to the following files would be overwritten by merge"

  17. 17

    How to read data files included in the app

  18. 18

    How to read data files included in the app

  19. 19

    How to use included Files in Executables Jar

  20. 20

    How to include a file in already included files in php?

  21. 21

    How to handle dual ABI in GCC 5?

  22. 22

    How to handle error compiling GCC 4.7.0 using GCC 6.2.1

  23. 23

    How to XHR local files?

  24. 24

    How to set PHPStorm to check for variable usage in required/included files? How to check variable definition in required/included files?

  25. 25

    Does PHP required or included files need to follow the order?

  26. 26

    Why does the executable binary file contain paths of included header files?

  27. 27

    Why does Visual Studio error when linking having files included?

  28. 28

    Does PHP required or included files need to follow the order?

  29. 29

    Does GCC merge files compiled together?

HotTag

Archive