Question Details

No question body available.

Tags

c linker include definition static-functions

Answers (3)

Accepted Answer Available
Accepted Answer
January 7, 2026 Score: 4 Rep: 220,484 Quality: Expert Completeness: 80%

Whenever we add a .c file to the list of files to compile, the compiler works with something called translation units which contains that .c file and all the headers that the file includes. This will then get compiled into an object file of some kind (.o in this case) that is then passed on to the linker.

In this case since you typed cc main.c func.c, you will have two such translation units originating from main.c and func.c both. These contain functions that have external linkage, meaning that the compiler/linker will have to expect that function to get called from elsewhere. Because of that, each resulting object file will contain a function call, which may be called from any other source file. This results in a conflict because of that, detected at the linker stage.

If you make it static then the function gets internal linkage, meaning that each translation unit still ends up with a local copy of the function but it is not exposed to other parts of the program. Where one of the functions (the one in func.c) is never called and therefore removed by link-time optimizations.

The easy fix would be to not include func.c in the compilation, since the contents of that file will get included from main anyway.

The correct fix however, is to follow best practices:

  • Never include anything but header (.h) files.
  • Every .c file shall have its corresponding header file with the same name, which it includes.
  • Every header file should have "header guards" (#ifndef MYHEADERH #define MYHEADERH ... #endif.)
  • Every public function in the .c file which should be used by other parts of the program should have a function declaration in the header file (along with the documentation of how to use it).
  • Every private function in the .c file not to be used by other parts of the program should be declared static and without a function declaration in the header. (It may still have a function declaration at the top of the .c file though.)
January 7, 2026 Score: 5 Rep: 36,669 Quality: Medium Completeness: 80%

There are 2 issues here:

  1. Wrong #include:

    You #include a c file. This should [almost] never be done.
    Instead create a header file like func.h with a declaration for the function:

    int call(void);
    

    And #include this header in every c file that uses call().
    At the moment with your #include "func.c", the linker encounters 2 definitions for call(): one in the translation unit of main.c and one in the translation unit of func.c.
    This is invalid - global symbols must generally be defined once.

  2. Making the function static:

    static in this context means that the function is limited to the current translation unit.
    Therefore each translation unit has "its own" call() function and the linker does not expect it to be unique and available globally.
    But as explained above this only hides the issue of the wrong #include explained above.

January 7, 2026 Score: 4 Rep: 233,911 Quality: Medium Completeness: 60%

The name of an object of function is called its identifier.

A translation unit is one source file being compiled as it appears after each #include directive in it is replaced with the contents of the included file.

In C, an identifier used in one place can refer to an identifier defined in a different place through a process called linkage.

When an object or function is declared at file scope (outside of any function), it has external linkage by default. With external linkage, an identifier used in one translation unit can refer to an identifier defined in another translation unit.

When you execute cc main.c func.c -o program, the command compiles main.c as one translation unit and separately compiles func.c as another translation unit. These compilations produce two temporary object files, and the command links those object files together.

When main.c has #include "func.c", the definition of call is included in main.c and is part of that translation unit. So this translation unit has a definition of call with external linkage.

You also compile func.c, and this translation unit also has a definition of call with external linkage.

When there are two definitions of the same identifier with external linkage, the C standard does not define the behavior. Most commonly, when there are two ordinary definitions of a symbol in object files, the linker reports an error.

When you define call with static int call(void), that changes its linkage to internal linkage. Internal linkage limits resolution of an identifier to the translation unit it is declared in. Then the use of call in main is resolved to the call that is defined in main.c, and the call that is defined in func.c is not involved and does not cause any conflict.