14

I want to include a .c file in another. Is it possible right? It works well if I include a header file in a .c file, but doesn't work as well if I include a .c file in another .c file.
I am using Visual Studio and I get the following error:

main.obj : error LNK2005: _sayHello already defined in sayHello.obj  
/* main.c  */
#include "sayHello.c"

int main()
{
    return 0;
}  
/* sayHello.c */

#include <stdio.h>

void sayHello()
{
    printf("Hello World");
}

I don't know what this error could mean. Time to ask more advanced C coders. :)

Andrew
  • 6,254
  • 16
  • 59
  • 93
  • 4
    Including a `*.c` file inside another `*.c` is very poor taste (for newbies). Leave that to experts. – Basile Starynkevitch May 04 '12 at 11:37
  • 2
    @BasileStarynkevitch: it's bad practice for experts, too. Believe it or not, compiling and linking a bunch of smaller translation units is less crazy-making than trying to compile one huge translation unit. – John Bode May 04 '12 at 11:47
  • 2
    *Why* do you want to do this? – jamesdlin May 04 '12 at 12:02
  • possible duplicate of [Including one C source file in another?](http://stackoverflow.com/questions/232693/including-one-c-source-file-in-another) – Eitan T Jun 17 '14 at 11:15
  • I never encountered using #include like this until a couple days ago when I was importing an existing project into Visual Studio. It was a pain in the ass. I had to manually track down and remove all of the #included .c files from the project. As others have pointed out, this is a seriously bad idea. – Toby Deshane Jan 04 '16 at 15:29
  • @JohnBode: We should not make blanket rules that it is bad practice for experts. In some situations, it is reasonable. E.g., having one master source code file does nothing but conditional inclusion to select a specific implementation of the same set of functions and then includes one source code file that provides that implementation is a reasonable use case. – Eric Postpischil Jun 15 '23 at 21:33
  • @EricPostpischil: That use case seems like something better managed with makefiles or similar. I've seen too many experts (including myself) say "don't worry, I know what I'm doing," which is when everyone else should start to panic. – John Bode Jun 15 '23 at 21:51
  • @JohnBode: Sometimes makefiles are an appropriate solution. Sometimes they are not. We should avoid making blanket rules. – Eric Postpischil Jun 15 '23 at 21:56
  • See [How to test a static function?](https://stackoverflow.com/q/593414/15168) for circumstances where it may be permissible and necessary for one file (a test harness) to include another (the code under test). It's an extraordinary scenario, not something to practice routinely. But when it is necessary, it can be a great help. – Jonathan Leffler Jun 23 '23 at 17:32

9 Answers9

36

I want to include a .c file in another.

No you don't. You really, really don't. Don't take any steps down this path; it only ends in pain and misery. This is bad practice even for trivial programs such as your example, much less for programs of any real complexity. A trivial, one-line change in one file will require you to rebuild both that file and anything that includes it, which is a waste of time. You lose the ability to control access to data and functions; everything in the included .c file is visible to the including file, even functions and file scope variables declared static. If you wind up including a .c file that includes another .c file that includes another .c file und so weiter, you could possibly wind up with a translation unit too large for the compiler to handle.

Separate compilation and linking is an unequivocal Good Thing. The only files you should include in your .c files are header files that describe an interface (type definitions, function prototype declarations, macro defintions, external declarations), not an implementation.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • "A trivial, one-line change in one file will require you to rebuild both that file and anything that includes it, which is a waste of time" --> isn't it the same if you would include a header file and change a line in it? – stdout Apr 12 '18 at 14:51
  • 2
    @zgulser: Yes, when you change an *interface* (macro definition, function delcaratoin, type definition, etc.), you have to rebuild everything that depends on that interface. However, if you only change an *implementation* of a function, no file other than the one containing that function should need to be be rebuilt. Unfortunately, by including .c files within other .c files, you wind up rebuilding the world when you change a line buried deep in a `for` loop. – John Bode Apr 12 '18 at 16:36
  • 4
    This is a very opinionated opinion. I would agree that making it a practice should be strongly discouraged in favor of libraries. For complex programs, it would be a inefficient, a tangled mess and quite possibly produce compile errors. But to say "No you don't. You really, really don't.", without context, is quite arrogant and presumptuous. I've done it many times for quick-and-dirty testing, benchmarking, and debugging...a simple way to put your target code in a simple test platform without the hassle of compile and linking or makefiles. – codechimp Aug 18 '20 at 19:42
13

It works, but you need to be careful with how you build the program. Also, as folks have pointed out in comments, it's generally considered a bad idea. It's unexpected, and it creates problems like these. There are few benetfits, especially for what seems like a trivial program. You should probably re-think this approach, altogether.

After doing something like this, you should only compile main.c, and not attempt to link it with the result of compiling sayHello.c, which you seem to be doing.

You might need to tell Visual Studio to exclude the latter file from the build.

Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
5

Yes, any '.c' file can be included into another program. As one include '.h' file like 'stdio.h' in the program. After that we can call those function written into this external file.

test.c::

#include<stdio.h>
#include<conio.h>
void xprint()
{
    printf("Hello World!");
}

main.c::

#include "test.c"
void main()
{
   xprint();
   getch();
}

Output:: Hello World!

S. Pramanik
  • 51
  • 1
  • 3
4

This is a linker error. After compiling all your .c files to .obj files (done by the compiler) the linker "merges" them together to make your dll/exe. The linker has found that two objects declare the same function (which is obviously not allowed). In this case you would want the linker to only process main.obj and not sayhello.obj as well (as its code is already included in main.obj).

This is because in main.obj you will ALSO have the sayHello() function due to the include!

Bjørn van Dommelen
  • 1,057
  • 7
  • 13
2

sayHello.h

#include <stdio.h>
void sayHello(void);

main.c

#include "sayHello.h"

int main()
{
    sayHello();
    return 0;
}  
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
0

You probably defined two times this function

void sayHello()
{
printf("Hello World");
}

one in your current file and one in sayhello.c

You must remove one definition.

Quanteek
  • 254
  • 2
  • 11
0

The problem seems to be that sayHello.c got compiled into an object file called sayHello.obj, and main.c (also including all the source text from sayHello.c), got compiled into main.obj, and so both .obj files got a copy of all the external symbols (like non-static function definitions) from sayHello.c.

Then all the object files were supposed to get "linked" together to produce the final executable program file, but the linking breaks when any external symbols appear more than once.

If you find yourself in this situation, you need to stop linking sayHello.obj to main.obj (and then you might not want to compile sayHello.c by itself into its own object file at all).

If you manually control every step of the build (like you might when using the CLI of your compiler), this is often just a matter of excluding that object file from the invocation of the linker or compiler.

Since you are using Visual Studio, it's probably making a bunch of assumptions for you, like "every .c file should be compiled into its own object file, and all those object files should be linked together", and you have to find a way to circumvent or disable this assumption for sayHello.c.

One easy and somewhat idiomatic solution might be to rename sayHello.c into sayHello.c.inc.

mtraceur
  • 3,254
  • 24
  • 33
0
//THIS IS THE MAIN FILE//
#include "test.c"
int main()
{
    multi(10);
}


//THIS IS THE TEST FILE//
#include<stdio.h>
void multi(int a)
{
    printf("%d",a*2);
}

POINTS TO BE NOTED:

  1. Here you need to run the program which contains "main()" function.
  2. You can avoid the "stdio.h" header file in main function. Because, you are including the file which already contains the "stdio.h" header file.
  3. You have to call the function from the "main" file.
  4. The including file should be "file_name.c" not "file_name.h". Because usually we use .h extension for the header file. Since we are including another program file and not the header file, we have to use .c. Otherwise it will give you Fatal Error and the Compilation gets terminated.
0

You can declare your function as static inline if you just want it to work. However, as people have suggested, approaching this problem with separate .h and .c files would be better.

static inline void sayHello()
{
    printf("Hello World");
}