hi lets say you have a big application and you want to break it up to many files... The ideal would be if you can have the application in one .c {i.e main.c} file your types and includes in another file {types.h} and your functions in a seperate file {functions.c} and their declarations in their own header file{i.e. functions.h}.... So we have these files for a simple application:

types.h

//here i would also put all the includes my main application needs
//i am not sure this is a good practise...


//let tA be a seperate type...

typedef int tA;

func.h

#include "func.c"

#ifndef FUNC_H
#define FUNC_H 1

void fadd(tA, tA);

#endif

func.c

void fadd(tA x, tA y)
{
	printf("%d\n", x+y);
}

main.c

#include <stdio.h>
#include "func.h"
#include "types.h"

int main()
{
	tA a=5;
	tA b=6;

	fadd(5,6);

              return 0;
}

i think that the benefit from this seperation would be:: extra readability + being able to alter the main application without recompiling the functions{just relink them} or alter the functions without recompiling the application{just re-link}....

The problem is that i can't get the seperation to work...and i haven't been able to find a source to address this problem...

Dani AI

Generated

Good groundwork by (compile vs link) and thanks to for the reading tips. A couple of focused, practical points that pick up on ’s follow‑up about globals and reducing unnecessary recompiles.

Keep one true definition for globals, declare them elsewhere. Put the actual definition in a single .c file and place an extern declaration in a header that other files include. Example pattern:

/* globals.h */
#ifndef GLOBALS_H
#define GLOBALS_H

#include <stdio.h>

extern FILE *g_log_file;   /* declaration only */

#endif
/* globals.c */
#include "globals.h"

FILE *g_log_file = NULL;   /* single definition */

Do not define globals in headers. If the variable should be private to one translation unit, make it static in that .c file so it cannot collide with other modules.

Avoid heavy headers in public headers: prefer forward declarations / opaque pointers when the full type is only needed inside implementation. Example:

/* api.h */
#ifndef API_H
#define API_H

typedef struct Foo Foo;    /* opaque */
Foo *foo_create(void);
void foo_destroy(Foo *);

#endif

and put struct Foo { ... }; inside foo.c. This reduces recompiles when internals change.

Other tips: give globals clear, module‑prefixed names to avoid clashes, prefer accessor functions over wide‑scope globals for initialization control and thread safety, and be cautious with global object initialization order in C++ (constructors across translation units). For build workflow, compile modules separately to object files or a library so only changed modules need recompiling, then link them together — that’s how you get the relink-only behavior you described.

Recommended Answers

All 5 Replies

1. Don't #include C files, otherwise you end up with "multiply declared" errors from the linker.

2. If you have multiple source files, as in this example, the command line would be something like gcc main.c func.c In an IDE environment, you would add the two source files to your project.

3. func.c would include func.h, so that when func.c is compiled, the prototype and definition get checked.

4. func.h needs types.h, for the prototype.

Splitting things up is one of those easy things which comes with practice.
Having some design ideas sketched out to being with will give you a lot of ideas on how the various modules will be structured and the interfaces between them.

one of the great classics of c++ deals with this topic in depth; 'Large-Scale C++ Software Design' by John Lakos. http://www.amazon.com/Large-Scale-Software-Design-John-Lakos/dp/0201633620

'More C++ Gems' by Stanley Lippman (F), Robert C. Martin (E) http://www.amazon.com/More-Gems-SIGS-Reference-Library/dp/0521786185/ref=sid_dp_dp/002-1745891-8300801 has three articles by John Lakos. these are a compact version of his seminal work.

note: the book is dated as far as c++ standards go; the issues it deals with are timeless.

thank you for your replies and for the book recommendations{because frankly i haven't bumped in a book that treats this subject}... the problem is that i am in greece so the books are a bit hard to find{i must order from amazon}... so i would like some more help...

I don't use an IDE and my goal is to learn how to do this code "break up" in order to build a makefile...

from i what i understood i made the following changes:::
types.h

//here i would also put all the includes my main application needs
//i am not sure this is a good practise...

#ifndef TYPES_H
#define TYPES_H 1
//let tA be a seperate type...

typedef int tA;

#endif

func.h

#include "types.h"

#ifndef FUNC_H
#define FUNC_H 1

void fadd(tA, tA);

#endif

func.c

#include "func.h"
#include "types.h"
#include <stdio.h>

void fadd(tA x, tA y)
{
	printf("%d\n", x+y);
}

main.c

#include <stdio.h>
#include "func.h"
#include "types.h"

int main()
{
	tA a=5;
	tA b=6;

	fadd(5,6);

              return 0;
}

i compile using gcc main.c func.c what i can't uderstand is the following::

1) if i include in func.c the file func.h and then in my main application i include the func.h file where does the compiler know where to look for the function definition {there is no link to func.c}

2) is it possible to avoid certain inclusions for example the types.h is included both in func.h and both func.c

3)if i make a makefile i would have a rule for the func.c and another rule for the main.c {which would have as a dependecy the rule for func.c}?

Splitting things up is one of those easy things which comes with practice.

i imagine your are right, the problem is that i haven't found any solid examples to learn from... so everytime i make a programming project{2-3 times so far--i am new!}, it takes time to find the "correct" split...and basically it comes from trial and error so this time i decided to settle with this problem once and for all...

thanks again for your posts,
nicolas

> where does the compiler know where to look for the function definition
The compiler doesn't. It only needs to know what things look like, not where they are. It's the linker (the next step, which is usually invisible) which combines everything together to produce a runnable program.

> is it possible to avoid certain inclusions for example the types.h is included both in func.h and both func.c
You can leave types.h out of func.h, but then you have to remember to include types.h in all the places that include func.h.
Whether or not this is a "good thing" is open to debate. On the one hand, it's very easy to see in any source file exactly what the dependencies are. On the other hand, if func.h suddenly needs stuff.h as well, then you have a massive edit job on your hands.

> if i make a makefile i would have a rule for the func.c and another rule for the main.c
There would be 3 rules

main.o depends on main.c (and some headers)
func.o depends on func.c (and some headers)
prog.exe depends on main.o and func.o

> i compile using gcc main.c func.c
Try gcc -v main.c func.c And you'll see all the steps which the compiler goes through.

When you do this via a makefile, it will look something like this

gcc -c main.c
gcc -c func.c
gcc -o prog.exe main.o func.o

You can even type these by hand (with -v if you want) to see what happens.

thanks for all the details :) ... One last question if i have some globals {i.e. a file pointer} that they are used in main and in some of the functions, where is the right place to put them...Is it the types.h or somewhere else?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.