cone-definition-ruleinclude-guardsprogram-structure

How do you define functions in header files?


The setup

If I have a program like this

A header file that declares my main library function, primary() and defines a short simple helper function, helper().

/* primary_header.h */
#ifndef _PRIMARY_HEADER_H
#define _PRIMARY_HEADER_H

#include <stdio.h>

/* Forward declare the primary workhorse function */
void primary();

/* Also define a helper function */
void helper()
{
    printf("I'm a helper function and I helped!\n");
}
#endif /* _PRIMARY_HEADER_H */

The implementation file for my primary function that defines it.

/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>

/* Define the primary workhorse function */
void primary()
{
    /* do the main work */
    printf("I'm the primary function, I'm doin' work.\n");

    /* also get some help from the helper function */
    helper();
}

a main() file that tests the code by calling primary()

/* main.c */
#include "primary_header.h"

int main()
{
    /* just call the primary function */
    primary();
}

The Problem

Using

gcc main.c primary_impl.c

does not link because the primary_header.h file gets included twice and therefore there is an illegal double definition of the function helper(). What is the correct way to structure the source code for this project such that double definitions do not happen?


Solution

  • You should only write your function's prototype in the header file, the body of your function should be written in a .c file.

    Do this :

    primary_header.h

    /* primary_header.h */
    #ifndef PRIMARY_HEADER_H
    #define PRIMARY_HEADER_H
    
    #include <stdio.h>
    
    /* Forward declare the primary workhorse function */
    void primary(void);
    
    /* Also define a helper function */
    void helper(void);
    
    #endif /* PRIMARY_HEADER_H */
    

    primary_impl.c

    /* primary_impl.c */
    #include "primary_header.h"
    #include <stdio.h>
    
    /* Define the primary workhorse function */
    void primary()
    {
        /* do the main work */
        printf("I'm the primary function, I'm doin' work.\n");
    
        /* also get some help from the helper function */
        helper();
    }
    
    void helper()
    {
        printf("I'm a helper function and I helped!\n");
    }
    

    Edit: change _PRIMARY_HEADER_H to PRIMARY_HEADER_H. As @Jonathan Leffler and @Pablo said, underscore names are reserved identifiers