tags:

views:

301

answers:

11

Hi

I came across some codes in the following way

//file.c  
#include <stdlib.h>

void print(void){

    printf("Hello world\n");
}

and

//file main.c  
#include <stdio.h>
#include "file.c"

int main(int argc, char *argv[]){

    print();

    return EXIT_SUCCESS;
}

Is there any flaw in this kind of programming style? I am not able to make out the flaw although I feel so, because somewhere I read that separating the implementation into *.h and *.c file helps compiler check for consistency. I don't understand what is meant by consistency.
I would be deeply thankful for some suggestions.

--thanks

A: 

In the .h files you should place function prototypes. For example, in your code you should have:

//file.h
void print(void);

//file.c
void
print(void)
{
   printf("Hello world\n");
}
//file main.c  
#include <stdio.h>
#include "file.h"

int main(int argc, char *argv[]){

    print();

    return EXIT_SUCCESS;
}
Macarse
The file1.c is an example showing the point that there is executable code in an included file not the real program being used.
C.W.Holeman II
Yes, I notice now reading again his question. I read #include "file.h" and didn't notice the real problem. I will erase that part of my answer. Thanks.
Macarse
+7  A: 

You're going to have problems if you include file.c in more than one source code file which combine to make a library/executable, since you'll have duplicate method implementations. The above strikes me as a poor means of sharing/reusing code, and is not to be recommended.

Brian Agnew
+10  A: 

Nothing prevents you from including .c files. However, separating declaration (in .h files) and implementation (and .c files) and then including only .h files has several advantages :

  • Compile time. Your declaration usually changes less than your implementation. If you include only .h files, and makes a change in your implementation (in the .c file), then you only have to recompile one .c file, instead of all the files which include the modified file.

  • Readability and management of interfaces. All your declarations can be checked in a single glance at the (usually) small .h file whereas the .c file is filled with lines and lines of code. Moreover it helps you determine which file see which functions and variables. For example, to avoid having a global variable included where you don't want it.

Ksempac
+8  A: 

It's a common expectation that the compiler should compile .c files. .h files are not directly given to the compiler. They are usually only included within .c files.

Thus, your code is expected to compile by something like:

gcc main.c file.c

rather than only gcc main.c. That command would fail in the linking stage as it sees duplicate symbols.

Mehrdad Afshari
A: 

There is nothing wrong from a C language perspective with including a .c file in a program. The C language cares not about the extension of the file, C++ in fact often omits an extension on certain header files to avoid conflicts.

But from the perspective of a programmer, yeah this is odd. Most programmers will operate on the assumption that a .c file will not be included and this can cause problems via incorrect assumptions. It's best to avoid this practice. If you find you must use it, it's a sign of poor design.

JaredPar
+1  A: 

Yes, this is permitted.

Using this is an advanced topic.

  • It slows down development compile time (cheaper to compile only what is necessary).
  • It speeds up deployment compile time (all files are out of date).
  • It allows the compiler to inline functions across module boundaries.
  • It allows a trick to control exported symbols from a library while keeping it modular.
  • It might confuse the debugger.
Joshua
+1  A: 

It is not uncommon to include data in another file if it is more convenient to separate it from the code. For example, XPM or raw BMP data in a char array could be included to embed an image in the program in this way. If the data is generated from another build step then it makes sense to include the file.

I would suggest using a different file extension to avoid confusion (e.g. *.inc, *.dat, etc.).

Judge Maygarden
A: 

There are only two reasons that I know of for including C files (and which make sense):

  • inline functions which are non trivial, but that's really a matter of style
  • share implementation of private (static) functions by including the same file in several other files. That's actually the only way to do it in a purely platform independent way (but toolchain specific tricks like hidden attribute for gcc, etc... are much better if they are available)

The flaws:

  • you compile several times the same code
  • if not used sparingly, it quickly leads to multiple defined symbols for public symbols, in a way which is difficult to debug (include files which include other files...)
David Cournapeau
A: 

It is bad style, but one other reason to do it is that it can be used a part of a trick using the ## token concatenation operator to do a kind of poor man's templating in C.

Note that this fairly evil, isn't recommended, and will produce code that's hard to debug and maintain, but you can do something like the following:

mytemplate.c:

MyTemplateFunction_ ## MYTYPE(MYTYPE x)
{
  // function code that works with all used TYPEs
}

main.c:

#define MYTYPE float
#include "mytemplate.c"
#undef MYTYPE

#define MYTYPE int
#include "mytemplate.c"
#undef MYTYPE

int main(int, char*)
{
  float f;
  int i;
  MyTemplateFunction_float(f);
  MyTemplateFunction_int(i);
  return 0;
}
therefromhere
A: 

The evils of macros can be exacerbated:

file1.c

#define bottom arse

file2.c

int f()
{
    int arse = 4;
    bottom = 3;
    printf("%d", arse);
}

main.c

#include "file1.c"
#include "file2.c"

void main()
{
    f();
}

Indeed a convoluted example. But usually you wouldn't notice it because a macro's scope is the file it is in.

I did actually get this bug, I was importing some lib code into a new project and couldn't be bothered to write the Makefile, so I just generated an all.cpp which included all the sources from the library. And it didn't work as expected due to macro pollution. Took me a while to figure it out.

Max Howell
A: 

It's fine for the programs of this length.

ilya n.