You are not logged in.

#1 2010-09-18 13:02:23

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

C Programming: What goes in a header file?

I am programming in C and I want to improve my style and quality of code.

I would like to know the best way to structure a header and what kind of things I should be placing in headers versus in main? what things should I compile as stand alone C files?

The way I do things now is basically use headers as a store house for functions that fall under a general umbrella.

For example if the program is pretty big and implements a lot of different things I may use one header for all the file manipulation functions like sorting, creating, removing etc. (essentially making a mini-library) and I may use another header for network functions like sending the files etc. All while main is just the general structure of the program, and it's where I apply threads and general program flow all while the real power comes from the headers and functions. I try to keep main pretty minimal.

Is this bad coding practice? I am pretty much self taught so I would like to know if I am doing something wrong.

Offline

#2 2010-09-18 13:03:35

Allan
Pacman
From: Brisbane, AU
Registered: 2007-06-09
Posts: 11,487
Website

Re: C Programming: What goes in a header file?

Headers are usually just function prototypes.  The implementation goes in the .c file.

Offline

#3 2010-09-18 13:05:35

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

Re: C Programming: What goes in a header file?

That is basically what I have been doing. I basically make functions in main and when they work I pull them out and toss them in a header that falls under the 'umbrella' of its use.

Offline

#4 2010-09-18 13:12:18

Allan
Pacman
From: Brisbane, AU
Registered: 2007-06-09
Posts: 11,487
Website

Re: C Programming: What goes in a header file?

It sounds like you are putting the whole function in the header, which is different than just putting the prototype in...

Offline

#5 2010-09-18 13:14:57

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

Re: C Programming: What goes in a header file?

When I mean toss it it, I mean the prototype. I cut the declaration out.

smile

I would put something like this in a header:

int add(int x, int y){
return x+y;
}

^this is a prototype right?

Last edited by Google (2010-09-18 13:15:22)

Offline

#6 2010-09-18 13:29:54

bernarcher
Forum Fellow
From: Germany
Registered: 2009-02-17
Posts: 2,281

Re: C Programming: What goes in a header file?

Google wrote:

When I mean toss it it, I mean the prototype. I cut the declaration out.

smile

I would put something like this in a header:

int add(int x, int y){
return x+y;
}

^this is a prototype right?

No, this is the function definition. The prototype is the declaration of this function, conceptually the initial line without the body, like in your example:

int add(int x, int y);

Last edited by bernarcher (2010-09-18 13:30:18)


To know or not to know ...
... the questions remain forever.

Offline

#7 2010-09-18 13:36:10

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

Re: C Programming: What goes in a header file?

So the header contains the declarations, and the .c contains the definitions? I think I had it backwards!

Offline

#8 2010-09-18 13:38:41

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,965
Website

Re: C Programming: What goes in a header file?

Google wrote:

So the header contains the declarations, and the .c contains the definitions? I think I had it backwards!


There's a "you had your head up your ass" joke in here somewhere, but I can't find it.


My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

#9 2010-09-18 13:41:30

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

Re: C Programming: What goes in a header file?

Hmm, reminds me of an article I read about people who insist on putting an X in their online alias.

Offline

#10 2010-09-18 14:39:49

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: C Programming: What goes in a header file?

Typically a project will have pairs of files with the same name but different extensions -- stuff.c contains definitions whereas stuff.h contains delcarations of the things stuff.c wants to export to other places.  When writing a program that uses stuff, you put #include "stuff.h" in your main file and compile stuff.c and main.c separately, then link together stuff.o and main.o into an executable.

The purpose of header files is to check the correct use of external data and functions at compile time without having to recompile it all whenever you change any single file.  If you put definitions in your header files, you're essentially copying your whole project into one file at compile time.  For large projects you could waste hours recompiling the entire thing because you made a minor change in main() -- not good.

Offline

#11 2010-09-18 15:16:58

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

Re: C Programming: What goes in a header file?

That makes sense. I haven't worked on any large project but I do like separating code because it makes things more readable, and you can re-use a lot of code from certain things.

Offline

#12 2010-09-18 18:21:02

fsckd
Forum Fellow
Registered: 2009-06-15
Posts: 4,173

Re: C Programming: What goes in a header file?

Similar for libraries. One day, take a look at the headers you use.


aur S & M :: forum rules :: Community Ethos
Resources for Women, POC, LGBT*, and allies

Offline

#13 2010-09-18 19:01:14

yejun
Member
Registered: 2009-10-21
Posts: 66

Re: C Programming: What goes in a header file?

In .h you should put

int add(int, int);

Offline

#14 2010-09-18 21:02:05

cmtptr
Member
Registered: 2008-09-01
Posts: 135

Re: C Programming: What goes in a header file?

By no means any kind of public standard that I know of, but the following is an example of my typical standard practices.

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <pathHeaders.h>

#include "localHeaders.h"

/* macros specific to this module are prefixed with the module name */
#define WIDGET_MACRO 123

/* if a tag is necessary, use the typedef name preceeded by an underscore */
typedef struct _Widget {
    char           *whatev;
    int            hello;
    struct _Widget *next;
} Widget;

/* functions and global variables (ew!) specific to this
   module are prefixed with the module name and an underscore */

/* short description of this function */
extern int widget_wiggleWoggle(
        Widget       *this,
        const Widget *that
);

/* malloc and initialize a widget */
extern Widget *widget_new(
        char *whatev,
        int   hello
);

/* uninitialize and free a widget */
extern void widget_free(
        Widget *this
);

#endif /* WIDGET_H */

widget.c:

#include <assert.h>
#include <otherPathHeaders.h>
#include <stdlib.h>

#include "localHeaders.h"
#include "widget.h"

/* static functions and variables private to this
   module are preceeded with one underscore */
static Widget *_lastWiggled;

static void _staticFunction(int *dest, int src)
{
    /* don't assert parameters in private functions;
       assume the extern'd functions already asserted them */
    *dest |= src;
    *dest <<= 1;
}

int widget_wiggleWoggle(Widget *this, const Widget *that)
{
    size_t i;

    assert(this);
    assert(that);

    for (i = 0; i < sizeof this->hello; i ++) {
        _staticFunction(&this->hello, that->hello);
    }

    _lastWiggled = this;
    return this->hello;
}

Widget *widget_new(char *whatev, int hello)
{
    Widget *this;

    assert(whatev);

    this = malloc(sizeof *this);
    if (!this)
        return 0;

    /* do necessary stuff to initialize this */
    this->whatev = whatev;
    this->hello  = hello;

    return this;
}

void widget_free(Widget *this)
{
    assert(this);

    /* do necessary stuff before freeing this */
    if (_lastWiggled == this)
        _lastWiggled = 0;

    free(this);
}

Last edited by cmtptr (2010-09-18 21:14:32)

Offline

#15 2010-09-18 22:26:11

codycarey
Member
Registered: 2009-08-21
Posts: 154

Re: C Programming: What goes in a header file?

You'll also generally put inline functions in the header files as well.

Offline

#16 2010-09-19 03:49:29

cmtptr
Member
Registered: 2008-09-01
Posts: 135

Re: C Programming: What goes in a header file?

codycarey wrote:

You'll also generally put inline functions in the header files as well.

You would?  Why?

Offline

#17 2010-09-19 05:31:21

yejun
Member
Registered: 2009-10-21
Posts: 66

Re: C Programming: What goes in a header file?

cmtptr wrote:
codycarey wrote:

You'll also generally put inline functions in the header files as well.

You would?  Why?

Because if you put normal function in header file, it will cause conflict, but not inline function.

You should also read boost library, which is almost entirely written in c++ header files. Not much you can do with c header files though, maybe some macro programming.

Last edited by yejun (2010-09-19 05:37:52)

Offline

#18 2010-09-19 09:19:17

Leffe
Member
Registered: 2006-05-30
Posts: 47

Re: C Programming: What goes in a header file?

cmtptr wrote:
/* short description of this function */
extern int widget_wiggleWoggle(
        Widget       *this,
        const Widget *that
);

extern is implied for function declarations.

yejun wrote:

Because if you put normal function in header file, it will cause conflict, but not inline function.

Another option is to make the functions static, which usually has the same result as inline.

Offline

#19 2010-09-19 09:23:08

Google
Member
From: Mountain View, California
Registered: 2010-05-31
Posts: 484
Website

Re: C Programming: What goes in a header file?

Thanks, that makes a lot of sense!

Offline

#20 2010-09-19 14:04:51

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: C Programming: What goes in a header file?

Leffe wrote:

Another option is to make the functions static, which usually has the same result as inline.

Not at all.  static in a file-scope function declaration gives the identifier internal linkage, which basically means that it isn't visible from any other source code file.  Referencing a function with internal linkage from some other file is a link-time error.  inline tells the compiler that a particular function definition is a good candidate for inlining, which means that no object code is generated and the content of the function is inserted in-line wherever the function is called.  Inline functions must always be defined in every file in which they are declared, which is why they are good candidates for placing in header files.  Using an inline function that hasn't been defined is a compile-time error, although for semantic reasons I think it can't be detected until link time.

It's true that inline is only a suggestion to the compiler, and so it's quite possible that inline and static occasionally have apparently the same effect.  But by no means are they interchangeable, and there's nothing useful that can be learned from conflating the two meanings.

As an aside, I forgot to mention this, but cmptr used it: your .c file should include the .h file of the same name (widget.c #includes "widget.h").  This ensures that the interface you export to other files is compatible with the internal workings of the program; e.g. it will raise a compile-time error if you declare "double val;" in the header and "float val;" in the .c file.

Offline

#21 2010-09-19 21:02:50

Leffe
Member
Registered: 2006-05-30
Posts: 47

Re: C Programming: What goes in a header file?

Trent wrote:

Not at all.  static in a file-scope function declaration gives the identifier internal linkage, which basically means that it isn't visible from any other source code file.  Referencing a function with internal linkage from some other file is a link-time error.  inline tells the compiler that a particular function definition is a good candidate for inlining, which means that no object code is generated and the content of the function is inserted in-line wherever the function is called.  Inline functions must always be defined in every file in which they are declared, which is why they are good candidates for placing in header files.  Using an inline function that hasn't been defined is a compile-time error, although for semantic reasons I think it can't be detected until link time.

It's true that inline is only a suggestion to the compiler, and so it's quite possible that inline and static occasionally have apparently the same effect.  But by no means are they interchangeable, and there's nothing useful that can be learned from conflating the two meanings.

I was commenting on having the function definition in the header file... in which case I now realize you have to make the function static whether you use inline or not.

Offline

#22 2010-09-20 00:42:08

tavianator
Member
From: Waterloo, ON, Canada
Registered: 2007-08-21
Posts: 859
Website

Re: C Programming: What goes in a header file?

Leffe wrote:

I was commenting on having the function definition in the header file... in which case I now realize you have to make the function static whether you use inline or not.

That's not true at all.  There's different semantics for inline depending on which standard you're using (GNU C89, ISO C99, and C++).  Briefly, for GNU C89, all inline function definitions should say "extern inline" except one, which should just say "inline".  For C99, all inline function definitions should say "inline" except one, which should have "inline" left out.  And for C++, everything should just say "inline".  You can read more here.

And here's some macros I once wrote to automate the whole process.

Offline

#23 2010-09-20 14:10:43

drcouzelis
Member
From: Connecticut, USA
Registered: 2009-11-09
Posts: 4,092
Website

Re: C Programming: What goes in a header file?

cmtptr wrote:

By no means any kind of public standard that I know of, but the following is an example of my typical standard practices...

The examples from cmtptr look very similar to my code, although I don't use "static" on any function declarations, and I pretty much never use the "inline" and "extern" commands.

One big difference in my code is something I started doing recently: I put as few "#include" commands in a header file as possible. Instead, in my header file I add as many re-declarations as needed (I only end up needing them for "struct" and "enum" declarations) and put all of my "#include" commands in the ".c" file. The benefit of this is that it removes most problems when I need to do something like circular dependency. (for example, struct A has a pointer to a struct B which has a pointer to a struct A)

Ah, what the heck, here's an example from my project.

Header:

#ifndef WORLD_HEADER
#define WORLD_HEADER


#include <allegro.h>


#define MAX_ROOMS 40


typedef struct WORLD WORLD;
struct PLAYER;
struct ROOM;


typedef enum
{
  STORY_WORLD = 0,
  ENDLESS_WORLD
} WORLD_TYPE;


struct WORLD
{
  /**
   * What type of world this is.
   */
  WORLD_TYPE type;
  
  /**
   * Represents the player, aka the hero!
   */
  struct PLAYER *player;
  
  /**
   * A list of the rooms in this world.
   */
  struct ROOM *rooms[MAX_ROOMS];
  int num_rooms;
  int room_idx;
  
  /**
   * The room number that is currently occupied.
   * This may be greater than the number of rooms that
   * are currently in the world.
   */
  int room_num;
};


WORLD *create_world();
void destroy_world(WORLD *world);

void add_room(WORLD *world, struct ROOM *room);
void clear_rooms(WORLD *world);

void update_world(WORLD *world);
void paint_world(WORLD *world, BITMAP *canvas);


#endif

Source:

#include "character.h"
#include "player.h"
#include "room.h"
#include "sprite.h"
#include "world.h"



WORLD *create_world()
{
  WORLD *world;
  int i;

  world = malloc(sizeof(WORLD));

  world->type = STORY_WORLD;
  
  world->player = create_player();
  warp_sprite(world->player->character->sprite, ROWS - 3, COLS / 2);

  for (i = 0; i < MAX_ROOMS; i++) {
    world->rooms[i] = NULL;
  }

  world->num_rooms = 0;
  world->room_idx = 0;
  
  world->room_num = 0;

  return world;
}




void destroy_world(WORLD *world)
{
  if (world == NULL) {
    return;
  }

  destroy_player(world->player);
  
  clear_rooms(world);

  free(world);
}




void add_room(WORLD *world, ROOM *room)
{
  if (world == NULL || room == NULL) {
    return;
  }
  
  world->rooms[world->num_rooms] = room;
  world->num_rooms++;
}




void clear_rooms(WORLD *world)
{
  int i;
  
  if (world == NULL) {
    return;
  }
  
  for (i = 0; i < MAX_ROOMS; i++) {
    destroy_room(world->rooms[i]);
  }
}




void update_world(WORLD *world)
{
  update_player(world->player, world);
  update_room(world->rooms[world->room_idx]);
}




void paint_world(WORLD *world, BITMAP *canvas)
{
  paint_room(world->rooms[world->room_idx], canvas);
  paint_sprite(world->player->character->sprite, canvas);
}

Offline

Board footer

Powered by FluxBB