Thread: Simple include issue with code::blocks

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    486

    Simple include issue with code::blocks

    I am starting a new project in codeblocks using the default settings. I have three .c files that I need to link together, and I am apparently doing it wrong.

    main.c looks like this:

    Code:
    #include<time.h>
    #include<windows.h>
    #include<stdint.h>
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    #include"detection.h"
    #include"io.h"
    #include"butterworth.h"
    
    
    
    int main(int argc, char **argv)
    {
        //allocate and read configuration struct
        configuration *config;
        if ((config = malloc(sizeof(configuration)))==NULL)
        {
            printf("Cannot allocate config structure\n");
            abort();
        }
        read_config(config);
    
    
        return 0;
    }
    detection.c looks like this:

    Code:
    #include"detection.h"
    nothing there yet, still working on getting things set up properly.


    detection.h defines a struct

    Code:
    struct Configuration
    {
        ...stuff...
    };
    typedef struct Configuration configuration;
    io.c reads stuff into the struct

    Code:
    #include"io.h"
    #define STRLENGTH 1024
    void read_config(configuration *config)
    {
         ...stuff....
    }
    and io.h just declares that function

    Code:
    void read_config(configuration *config);
    When I try to build, I get "Error: unknown type name configuration"

    so apparently things are not being included properly. Can anyone suggest what I am doing wrong?
    C is fun

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    if io.c or io.h doesn't include detection.h, that struct won't be visible to that source file.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    welp, that should have been obvious ^_^. I blame Friday morning with no coffee.

    I guess a better way to do it would be to declare all the structs that are needed in multiple .c files in a separate structs.h file and #include that in all of the .c files, along with appropriate include guards.
    C is fun

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by KBriggs View Post
    I guess a better way to do it would be to declare all the structs that are needed in multiple .c files in a separate structs.h file and #include that in all of the .c files, along with appropriate include guards.
    That really depends, though I'm guessing not. If all the .c files are going to be compiled into a single library, then a single .h file that defines the interface for that library (function prototypes), along with any structs, macros, etc, then that is fine. Otherwise, one .h file for each .c file is pretty typical, and usually provides better code organization -- and good organization always trumps time saved by only having to #include one header. In either case (library with one header, or one .h for each .c), make sure to only put the things that need "exporting" in there -- things that are needed by other code modules. No need to expose unnecessary functions, struct info, etc. Also, all header files should have include guards*.


    I think (without knowing your entire project/code structure), the best solution would be one .h for each .c file. Use include guards on all your headers. Then, if io.h and/or io.c need stuff from detection.h, they should each #include it. If main.c or foo.c or something else also needs definitions from detection.h, they should also #include it. Same goes for other headers -- #include them in every file that needs them. The include guards will prevent any issues with multiple definitions.


    * Of course there are exceptions (if you can still call them header files at that point), but you will probably know when you need to violate that rule.

  5. #5
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    Fair enough. My .h files now look like this:

    Code:
    #ifndef DETECTOR_H_INCLUDED
    #define DETECTOR_H_INCLUDED
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<string.h>
    #include<stdint.h>
    #include<inttypes.h>
    #include<time.h>
    
    struct Configuration
    {
        ...things...
    };
    typedef struct Configuration configuration;
    
    
    
    
    int signum(double num);
    
    #endif // DETECTOR_H_INCLUDED
    Code:
    #ifndef IO_H_INCLUDED
    #define IO_H_INCLUDED
    #include"detection.h"
    
    void read_config(configuration *config);
    #endif // IO_H_INCLUDED
    and main.c #includes both .h files:

    Code:
    #include"detection.h"
    #include"io.h"
    No need for guards there, correct?

    Additional, unrelated question. I am using uint64_t types, and the proper way to print these is
    Code:
    printf("%" PRIu64 "\n",num);
    That macro evaluates to "I64u" - why wouldn't I simply using

    Code:
    printf("%I64u\n",num);
    Does that imply loss of portability since that macro might be implementation dependent?
    C is fun

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by KBriggs View Post
    Fair enough. My .h files now look like this:

    Code:
    #ifndef DETECTOR_H_INCLUDED
    #define DETECTOR_H_INCLUDED
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<string.h>
    #include<stdint.h>
    #include<inttypes.h>
    #include<time.h>
    
    struct Configuration
    {
        ...things...
    };
    typedef struct Configuration configuration;
    
    
    
    
    int signum(double num);
    
    #endif // DETECTOR_H_INCLUDED
    Not quite right. Don't include all the headers you're using for the whole program, in one .h file. Each file (.c or .h) should only include the headers that it directly uses/references itself. Thus, if you don't reference anything from stdio.h in detector.h, don't include it in there. If all detector.h has is a struct/type definition and a function prototype, then it does not need to #include anything. Just include guards, the struct and . The .c files that use printf or whatever, will each #include <stdio.h>. Make sense?
    Quote Originally Posted by KBriggs View Post
    and main.c #includes both .h files:

    Code:
    #include"detection.h"
    #include"io.h"
    No need for guards there, correct?
    Correct, no need for the guards in the .c files, you only use them in the headers.
    Quote Originally Posted by KBriggs View Post
    Additional, unrelated question. I am using uint64_t types, and the proper way to print these is
    Code:
    printf("%" PRIu64 "\n",num);
    That macro evaluates to "I64u" - why wouldn't I simply using

    Code:
    printf("%I64u\n",num);
    Does that imply loss of portability since that macro might be implementation dependent?
    Yes, that is exactly what it implies. The standard states that PRIu64 and similar exist for printing types in stdint.h. What they are defined as is implementation defined/dependent.

  7. #7
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    Not quite right. Don't include all the headers you're using for the whole program, in one .h file. Each file (.c or .h) should only include the headers that it directly uses/references itself. Thus, if you don't reference anything from stdio.h in detector.h, don't include it in there. If all detector.h has is a struct/type definition and a function prototype, then it does not need to #include anything. Just include guards, the struct and . The .c files that use printf or whatever, will each #include <stdio.h>. Make sense?
    But if, for example, I remove the #define<inttypes.h> from detector.h, I get the error: unknown type uint64_t (there are a few of these declared in the struct). Doesn't the .h file where the struct is declared need that header file in it? Or should I be defining the struct in the .c file?
    C is fun

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by KBriggs View Post
    But if, for example, I remove the #define<inttypes.h> from detector.h, I get the error: unknown type uint64_t (there are a few of these declared in the struct). Doesn't the .h file where the struct is declared need that header file in it? Or should I be defining the struct in the .c file?
    Yes, but it probably only needs that header. I doubt detector.h needs stdio.h, stdlib.h, string.h, math.h, etc. Of course, without knowing what "...things..." are, I can't really say.

  9. #9
    Registered User
    Join Date
    Jun 2009
    Posts
    486
    Oh, I misunderstood. I thought you were discouraging me from including standard libraries in .h files altogether. All is clear now.
    C is fun

  10. #10
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by anduril462 View Post
    Each file (.c or .h) should only include the headers that it directly uses/references itself. Thus, if you don't reference anything from stdio.h in detector.h, don't include it in there.
    At the risk of encouraging bad habits, I always include the following header at the top of any module that uses any of the standard library facilities

    Code:
    #include "ct/standard_headers.h"
    Where "ct/" is a custom prefix to avoid name conflicts and "standard_headers.h" is a header that includes every header defined by the standard library. Obviously not all headers are needed, but if you think about it there is almost never a good reason not to include them all. When you distribute the source of this module to someone else you can either distribute your own custom header along with it or else you go replace such "shortcuts" with the actual standard headers that each module uses (a task which is best left to a major release of the project anyway).

    For 3rd party libraries you can do the same thing to save time and headaches. With these libraries you also sometimes need to rely on preprocessor black magic to get them to compile cleanly with your implementation, or to make sure you get feature X, Y or Z that is supplied with that library. This way you hide such nonsense behind a clean interface that everyone can understand. E.g.

    Code:
    #include "ct/standard_headers.h"
    #include "ct/apr_headers.h"
    #include "ct/curses_headers.h"
    #include "foo.h"
    
    void foo() {
        ...
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. #include <gdiPlus.h> problem with Code::Blocks
    By New_To_C++ in forum Windows Programming
    Replies: 18
    Last Post: 10-22-2011, 06:50 AM
  2. Replies: 6
    Last Post: 06-24-2010, 11:12 PM
  3. Simple JavaScript Code Issue
    By clegs in forum Tech Board
    Replies: 8
    Last Post: 07-14-2008, 03:11 AM
  4. Circular include issue
    By einarp in forum C++ Programming
    Replies: 10
    Last Post: 07-10-2006, 08:43 PM

Tags for this Thread