How to use multiple source and header files - c

I recently learnt how can we use multiple source files with header files to make code portable and hierarchical. In order to do so, I tried to create my tree program using this principle. Here are my files
b_tree_ds.h - This will contain a declaration of datastructure of node of a tree, which can be called to various functions implementing different functionality of the tree (which may be in different source files)
typedef struct node {
struct node* left;
struct node* right;
int key; // contains value
}NODE;
When i try adding a extern as in typedef extern struct node it gives a error of multiple storage class but if I miss it, I get error for multiple definitions.
Here are my other source files
traverse.h - contains declaration of traverse function
void traverse_print (NODE* p);
Here also I get error for unknown identifier NODE
traverse.c - contains definition to that function
#include <stdio.h>
#include "b_tree_ds.h"
#include "traverse.h"
void traverse_print(NODE* p)
{
if(p->left != NULL)
{
traverse_print(p->left);
}
if (p->right != NULL)
{
traverse_print(p->right);
}
printf ("\n%d",p->key);
}
Finally main.c
#include <stdio.h>
#include "traverse.h"
void main()
{
// input
NODE p;
printf("\nInput the tree");
input_tree (&p);
printf("\n\nThe tree is traversing ...\n")
traverse_print(&p);
}
void input_tree (NODE *p)
{
int in;
int c;
NODE *temp;
printf("\n Enter the key value for p: ");
scanf("%d", &in);
p->key =in;
printf ("\n\nIn relation to node with value %d",in);
printf ("Does it have left child (Y/N): ")
if ((c = getchar()) == Y);
{
//assign new memory to it.
temp = (NODE *)malloc(sizeof(NODE));
input_tree(temp);
}
printf ("\n\nIn relation to node with value %d",p->key);
printf ("\nDoes it have right child (Y/N): ")
if ((c = getchar()) == Y);
{
//assign new memory to it.
temp = (NODE *)malloc(sizeof(NODE));
input_tree(temp);
}
}
This is my first attempt to such practice, please suggest is the structuring of my program good or should I try something else.

You may be having problems because you haven't yet got a strong reason to split things up. A good reason would help you identify which parts belong together, and which parts are separate. So start with a simpler approach.
Split the program into three files, main.c, which contains main(), node.h, the header which ensures declarations are common across all the program, and hence is understood by the compiler, and node.c, the functions which manipulate the NODE structure.
Put the typedef ... NODE; and all the declarations of functions which manipulate NODE into one the node.h header file. So you could merge the existing header files into one, and call it node.h.
As Joop Eggen recommends, put #ifndef _NODE_H_ ... #endif around node.h contents to protect it against accidentally being #included twice.
Test that file is correct with a minimal main.c file containing:
#include "node.h"
int main() { return 0; }
and compile it. That should give no compilation errors. If it contains errors the fault is in the header file.
Put the functions that manipulate NODE, into a file called node.c, which will initially be:
#include "node.h"
compile and link that with main.c (gcc main.c node.c), and there should be no errors.
Build up the program is stages, adding code to the main.c file, the node.c file, and add declarations of functions in the node.c file into node.h. Add small amounts of code, and compile frequently (with warnings switched on, e.g. gcc -Wall main.c node.c) and test to make sure it is doing what you expect.
The program will eventually be complete.

I recommend looking at What are extern variables in C?.
You can include system headers such as <stdio.h> without having to worry about whether there are other headers needed to make use of its services. You should design your own headers in the same way. You should also prevent errors if your file is included multiple times (whether accidentally or deliberately).
You have:
b_tree_ds.h
typedef struct node {
struct node* left;
struct node* right;
int key; // contains value
} NODE;
Up to a point, this is fine; you just need to wrap it in header guards so reinclusion does no damage.
#ifndef B_TREE_DS_H_INCLUDED
#define B_TREE_DS_H_INCLUDED
typedef struct node {
struct node* left;
struct node* right;
int key; // contains value
} NODE;
#endif /* B_TREE_DS_H_INCLUDED */
You note:
When I try adding extern as in typedef extern struct node it gives a error of multiple storage class but if I miss it, I get error for multiple definitions.
Syntactically, extern, static, auto, register and typedef are all storage classes, and you can only have one storage class in a given declaration. That's why you get the multiple storage class error. The 'multiple definition' error will continue to be a problem until C2011 is widespread, and the header guards prevent that from being a problem. I think header guards will remain valuable even after C2011 is widely available.
traverse.h
void traverse_print (NODE* p);
As it stands, you can't simply write #include "traverse.h" to make use of its facilities. This is something to be avoided whenever possible. (See: Self-sufficent header files in C and C++,
What is a good reference documenting patterns of use of h files in C, and Should I use #include in headers.) Therefore, this should include b_tree_ds.h:
#ifndef TRAVERSE_H_INCLUDED
#define TRAVERSE_H_INCLUDED
#include "b_tree_ds.h"
extern void traverse_print(NODE *p);
#endif /* TRAVERSE_H_INCLUDED */
You could omit the header include guards on this header (assuming that b_tree_ds.h is self-protects), but it is simpler to be self-consistent in all headers.
There is one other possible technique that could be mentioned:
#ifndef TRAVERSE_H_INCLUDED
#define TRAVERSE_H_INCLUDED
typedef struct node NODE;
extern void traverse_print(NODE *p);
#endif /* TRAVERSE_H_INCLUDED */
This makes NODE into an opaque type; the user of the header traverse.h knows nothing about what's in a NODE. There are coordination issues to resolve that make this a less commonly used technique.
With these changes to the headers, then:
traverse.c only needs to include traverse.h (and should arguably include it before any other header to provide an automatic test of self-containment), but
If traverse.c includes both headers, there are no problems, regardless of the order in which they are included (and it doesn't matter if the repetition is direct or indirect).
Your main.c can include just traverse.h as shown and will be OK. With the original code, because main.c only included traverse.h and traverse.h did not include b_tree_ds.h, the code would not compile properly.

Forget about extern. In traverse.h you should include b_tree_ds.h. Some compilers have a pragma include once, but it does not hurt to surround the content of b_tree_ds.h with:
#ifndef B_TREE_DS_H
#define B_TREE_DS_H
...
#endif // B_TREE_DS_H
Look for compiler info on this case, and also on precompiled headers.
The above is a platform independent way of excluding content the second time.

Related

Can you include header file into another header file but when including the second header file in .c file, not automatically include the first one?

If I had a header file named "Header1.h" and another header file named "Header2.h", and include the first header file into the second, Header1 -> Header2, I would have access to Header1's code from Header2 . (For example, if I had defined a struct inside Header1, I could now make variables of that struct type in Header2).
Now if I had a .c file named "Main.c" and if I include "Header2.h" in "Main.c", Header2 -> Main, I would be able to access Header2's code from Main, but I would also be able to access Header1's code from Main as if I have included "Header1.h" inside "Main.c" specifically as well, Header1 -> Main. (For example, I could make a variable of type struct [the one defined in "Header1.h"] inside "Main.c").
Is there a way for me to restrict such access to "Header1.h" from "Main.c" and allow only "Header2.h" to be able to access information from "Header2.h", and perform similar "privatization" of a header file?
Transcribing a comment into the question:
Header1.h:
void printLinkedListImpl(Node* head)
{
while (head) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
Header2.h:
typedef struct {
Node* head;
int size;
void (*printLinkedList)(Node*);
} LinkedList;
LinkedList* LinkedListConstructorImpl() {
LinkedList* linkedList = (LinkedList*)malloc(sizeof(LinkedList));
linkedList->head = NULL;
linkedList->size = 0;
linkedList->printLinkedList = &printLinkedListImpl;
}
Main.c:
void runner() {
LinkedList* linkedList = LinkedListConstructorImpl();
}
I see two main options:
Header2.h needs the contents of Header1.h, in which case you can't sensibly want to omit the contents of Header1.h.
Header2.h does not need the contents of Header1.h, in which case Header2.h should not include Header1.h.
Write the code using the headers according to which option applies.
You would need a good reason not to decide on one or the other of those two options. However, it might be possible to define the header guard for Header1.h before including Header2.h:
Header1.h
#ifndef HEADER1_H
#define HEADER1_H
…
#endif
Header2.h
#ifndef HEADER2_H
#define HEADER2_H
#include "Header1.h"
…
#endif
Main.c
…
#define HEADER1_H
#include "Header2.h"
…
But, as I stated at the outset, either Header2.h needs the information from Header1.h to compile (in which case this will cause a compilation failure), or it doesn't (in which case Header2.h should not include Header1.h).
After transcribing the comment into the question:
Header files should not define general functions like it appears Header1.h does. A header should declare functions, types, enumerations, macros — and may perhaps define static inline functions — but should not define variables or functions. (See also How do I use extern to share variables between source files?). If you define functions in a header, the header can only be used by one source file, but the whole point of a header is to share information between source files.
If you're not sure how to build programs from multiple source files, that is a different question — one which has been answered many times. For example, Compiling multiple C files in a program, and there are numerous questions and answers for different IDEs that can be found by searching on SO with [c] compile multiple files program.

C project with multiple files (header files)

I'm fairly new to the C language, but have acquired some experience. Now I'm on my way creating larger projects with (more or less) complex data structures (e.g. Map (I will use Maps as an example thoughout)). Since I want my data structure code to be reusable for future projects, I like them being rather generic and in separate files.
Since C doesn't use/have Generics (like Java) oder Templates (like C++) or any similar concept I thought about using a globally defined data type like
typedef union {
int integer;
char * str;
// etc.
} data_t;
and put that in a main.h which will be included into all other (header) files (possible using guards). This works fairly well for me, but …
is there a way to integrate data structures into my data_t (which include main.h to use data_t) ?
The simple-but-obviously-not-working (due to circular includes) solution is to #include "map.h" in main.h while also including main.h in map.h; as mentioned, this doesn't work for obvious reasons.
Basically I want a Map that can hold other Maps, all while using only one data_t and one Map-implementation. Keeping track of which "layer" I am on will be done in the surrounding program (or maybe I can add some info in the data_t about its type, this is not the focus here).
I know that this will be possible when just using a void *; but I don't want unnecessary references for primitive datatypes like int if I don't have to.
Is there any clean way to do such behavior ?
Thank you !
(if any actual code is needed, tell me)
actual code
main.h which I want to contain general declarations like my data_t:
#ifndef _MAIN_H_
#define _MAIN_H_
#include "map.h"
typedef union {
int integer;
char * str;
map_t map;
} data_t;
#endif
map.h:
#ifndef _MAP_H_
#define _MAP_H_
#include "main.h"
typedef char * key_t;
typedef struct {
int (*hash_f)(key_t);
int size;
data_t * data;
} map_t;
int map_init(map_t * map, int (*hash_f)(key_t key));
int map_put(map_t map, key_t key, data_t data);
int map_get(map_t map, key_t key);
#endif
compiling with make:
% make
gcc -Wall -Wextra -Wpedantic -g -c main.c -o build/main.o
In file included from main.c:1:
./main.h:8:5: error: unknown type name 'map_t'
map_t map;
^
1 error generated.
make: *** [build/main.o] Error 1
Get your declarations and typedefinitions working within one source code file.
When that compiles, think what to put in a header. That way you make sure that at first you see what the compiler sees for one (each) code file your header gets included into.
If you cannot get it to work within one non-including code file, then you have a problem that cannot be solved with headers and guards.
If however you can do it, then just look at the single file and think "Now what do I want to also use in the next code file?" and put that into a header. (Make of course sure to only move declarations, typedefs, macro-defs into a header. Code, variable definitions do not go into headers.)
Circular dependencies cannot be solved by guards, only redefinitions due to (indirect) multiple inclusion.

Calling C functions in main with struct interfaces and additional C files

I have implemented a header file, "msg_queue.h" into a non-main file called "msg_queue.c." From here I created a main file known as "mq_test.c" whereby I created a message queue and called functions that were implemented in "msg_queue.c." Yet, when I run the 'make' command I seem to get this error for each function called:
"enqueue", referenced from:
_main in test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [qmsgtest] Error 1
What seems to be the problem, have I not implemented the structs correctly?
The headerFile:
#ifndef MessageQueue_H
#define MessageQueue_H
typedef struct node{
int data;
struct node *next;
} Node;
typedef struct {
Node *front;
Node *rear;
} MessageQueue;
void enqueue(...); // enqueue
...
#endif //MessageQueue_H
The file implementing the header:
#include "MessageQueue_H.h"
#ifndef MessageQueue_H
#define MessageQueue_H
/* Interface for integer MQueue */
typedef struct node{
int data;
struct node *next;
} Node;
typedef struct {
Node *front;
Node *rear;
} MQueue;
void enqueue(... ){ // enqueue
....
In the file implementing the header, msg_queue.c, you have an include guard:
#ifndef MSG_QUEUE_H
#define MSG_QUEUE_H
You have an include guard with the same name in msg_queue.h and as the header is preprocessed first, the implementation code is removed by the preprocessor (because MSG_QUEUE_H is already defined, your include guard is removing the implementation code), which is why it can't find the symbols.
You can check this yourself by running gcc or clang with the -E option on your source code. It will show you what the preprocessor has done to your code (which in your case means that you get only the prototypes of the functions, not the implementations).
So you need to remove the include guard in your .c source file.
It's worth noting that include guards aren't normally needed in .c implementation files, as these normally aren't included from other files.
In your example, you've also defined your struct types twice (both in the header and in the C file). This violates the single definition rule, so if you want to define your interface with the data types in the header, you should remove them from the source file, otherwise it won't compile.
There are other errors in this code which prevent it from compiling (at least in C99 mode which is what I've tested it as), but these are unrelated to your problem with the linker not being able to find the function symbol(s).

"already defined " error in VC++

I am learning to write programs in professional way. Like, by creating separate .C and .h file.i decided to write a simple code with structures but I am getting errors.
I have done these things :
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
struct list{
int a;
struct list *next;
};
typedef struct list LIST;
LIST *pHead=NULL,*pCurrent=NULL;
void display(void);
#endif
/*---list.c file ---*/
#include "main.h"
void display()
{
pHead->a=100;
printf("%d",pHead->a);
}
/*----main.h file-----*/
#ifndef MAIN_H
#define MAIN_H
#include<stdio.h>
#include "list.h"
#endif
/*---main.c file---*/
#include "main.h"
void main(void)
{
LIST *New=pHead;
display();
printf("\n\n%d",New->a);
getch();
}
when i compile the code , I am getting following errors
1>main.obj : error LNK2005: _pCurrent already defined in list.obj
1>main.obj : error LNK2005: _pHead already defined in list.obj
can anyone please tell me what I am doing wrong ? Am I including something twice because of which I am getting redeclaration error ?
This is because you define things in your header, as opposed to merely declaring them.
This:
LIST *pHead=NULL,*pCurrent=NULL;
means that every C file that includes the list header, tries to create two global variables. When you then link these C files together, those variables collide. This is broken, you should never do that. Never define things in a header.
You defined the objects in a header file and then included them in multiple source files thus breaking the one definition rule.
If you want to create global variables which you can use across different translation units, you should use the extern keyword.
Generally speaking, .c files contain embodiment of variables, functions, etc.; while .h files contain prototypes of variables, functions, etc., found in it's companion .c file.
It is generally the case that variable and function bodies are not placed in a .h file; only variable and function prototypes should be placed in .h files.
When considering how to split-up code into separate files, it is important to consider which functions, structures and macros are the most primitive. For example, if you write two functions, and function 'a' calls function 'b', function 'b' is most primitive.
The idea is to group functions into a 'c' file that are related, and are at a similar primitive level.
In the case of this question, the more primitive list functions should be embodied in list.c. Then 'list.h' is used to prototype functions and structures used by other less primitive .c files such as main.c.
The most primitive functions are also the most self sufficient. While less primitive functions should call more primitive functions, the reverse makes for clumsy code-flow.
Now to review the question code:
/*---list.c file ---*/
#include "main.h"
list.c should be considered as more primitive than main.c. Hence, having list.c include main.h is (professionally) not a good idea. list.c, being more primitive should be more self-sufficient.
Rather than including main.h, it would be better for list.c to include it's own list.h so that it has access to it's own `struct list' definition, etc.
void display()
{
pHead->a=100;
printf("%d",pHead->a);
}
In order to better isolate list.c, the above function should not reference a 'global' variable (pHead). Rather, it would be better to have the 'node to display' passed into the function as an argument.
With this in mind, here are how 'list.c' and 'list.h' might be improved:
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
} LIST_T;
extern void NodeDisplay(NODE_T *node);
#endif
/*---list.c file ---*/
#include <stdio.h> // printf()
#include "list.h" // NODE_T, LIST_T
void NodeDisplay(NODE_T *node)
{
printf("%d\n",pHead->a);
return;
}
Note that pHead and pCurrent are not prototyped, or embodied, in list.h or list.c Those variables are not used in list.c, and there is no functional reason to place them in list.h
Now examine main.h and main.c as they are in the question code:
/*----main.h file-----*/
#ifndef MAIN_H
#define MAIN_H
#include<stdio.h>
#include "list.h"
#endif
In isolation, what is the purpose that main.h requires stdio.h and list.h? If they were removed, would there be something left 'undefined' in 'main.h'? Perhaps these two include files don't really belong in main.h. "But if they are removed from main.h, why even have a main.h?" Good point. perhaps main.h serves no purpose and perhaps should not even exist.
The main.c file is the least primitive of all files, and shouldn't generally export anything to other (more primitive) files.
/*---main.c file---*/
#include "main.h"
void main(void)
{
LIST *New=pHead;
display();
printf("\n\n%d",New->a);
getch();
}
So what exactly does main.c need? It needs calls printf(), so it will need to include stdio.h. It calls display(), and references the LIST structure, so it needs list.h.
Yes, those .h files were included in main.h; good point. However, the code will be less clumsy (more professional) if main.c includes exactly what it needs explicitly.
With this philosophy in mind, here is a reworked main.c, without a superfluous main.h:
/*---main.c file---*/
#include <stdio.h> // printf()
#include <conio.h> // getch()
#include "list.h" // NodeDisplay(), LIST_T
int main(void)
{
LIST_T pList =
{
.head = NULL
};
/* Allocate & Insert a node into the list. */
NodeCreate(&pList, 100);
NodeDisplay(pList.head);
getch();
return(0);
}
This version of main.c includes exactly what is required, and appropriately calls less primitive functions. It has no need for 'global variables' because it passes its local storage to more primitive functions as needed.
Oh! you noticed the function NodeCreate()!
While the operation of allocating and inserting a new list node could be performed in main.c, such an operation is most likely a common occurrence that fits nicely with other linked list operations. Hence, add such a function to list.c:
/*---list.c file ---*/
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
#include "list.h" // NODE_T, LIST_T
void NodeDisplay(NODE_T *node)
{
printf("%d\n",node->a);
return;
}
void NodeCreate(LIST_T *list, int a)
{
NODE_T *newNode = malloc(sizeof(*newNode));
if(NULL == newNode)
{
fprintf(stderr, "malloc(newNode) failed.\n");
goto CLEANUP;
}
if(NULL == list)
{
fprintf(stderr, "Passing NULL as the list address not allowed.\n");
goto CLEANUP;
}
/* Initialize new node fields (payload) */
newNode->a = a;
/* Link newNode as new 'list head' node. */
newNode->next = list->head ? list->head->next : NULL;
list->head = newNode;
newNode=NULL;
CLEANUP:
if(newNode)
free(newNode);
return;
}
And so that this function can be called from the less primitive main.c, add a prototype of the function to list.h:
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
};
extern void NodeDisplay(NODE_T *node);
extern void NodeCreate(LIST_T *list, int a);
#endif
See spoiler code here.

How to partially declare a struct that is typedef'ed when in an include file

I'm trying to minimize interdependence of #include files as a general practice.
In xxx.h I have:
struct my_struct; // partial decl to satisfy use of my_struct*
void funct(struct my_struct* ms); // uses the partial def
How to do a similar partial decl with a typedef'd struct?
I have an actual decl in some third #include that looks like (say in yyy.h):
typedef struct my_data_s {
int ival;
... struct's other components ...
} my_data_t;
I just want a representative decl in xxx.h that reference the typedef:
typedef struct my_data_s my_data_t; // actual full decl is elsewhere
void funct2(my_data_t* md);
This attempt causes 'redefinition of typedef my_data_t' error. (Using gcc 4.4.3 / Ubuntu 10.4) Other random search attempts (e.g., add '{}' to typedef) also give errors.
I know the compiler only needs to know that the function requires a pointer, so it seems like this should be possible. So far, found nothing that compiles w/o errors/warnings.
I've looked at the other questions and answers, could not find this problem addressed. Seems like there should be a well-known way to do this(?!) (I know that I can #include yyy.y whenever I #include xxx.h - trying to avoid such dependencies.) Thanks.
Have you tried the simple approach:?
xxx.h
struct my_data_s;
typedef struct my_data_s my_data_t;
yyy.h
#include "decl.h"
struct my_data_s {
int foo;
};
C99 doesn't allow to repeat a typedef, C11 does.
Just do the typedef only once and always have it first:
typedef struct my_data my_data;
There also is no need to chose different names for the struct tag and the typedef identifier.
Here's what our group decided to do. It represents a compromise of several conflicting requirements/desires. I am posting to show another approach, so readers of the post have some variety to choose from. It represents the best answer for our situation.
obj_a_defs.h
// contains the definition
// #include'd only by other .h files
...
#define ... // as needed for struct definition
...
typedef struct obj_a {
...
} obj_a;
obj_a.h
// contains the 'full info' about obj_a: data and behaviors
// #include'd by other .c files
...
#include "obj_a_defs.h"
...
// declares functions that implement
// the behaviors associated with obj_a
obj_a.c
...
#include "obj_a.h"
...
// implementations of functions declared in obj_a.h
obj_b.h
// a 'user' of obj_a that uses obj_a as arg
#include "obj_a_defs.h" // to get the typedef
...
int some_b_funct(obj_a* obja, ...);
...
obj_b.c
// Defines the 'contract' that this implementation
// is meeting.
#include "obj_b.h"
...
// This .c file includes obj_a.h only if it
// uses the functions defined for obj_a.
// If obj_a is used only to 'pass through'
// to other modules, there's no need for
// this include.
#include "obj_a.h" // only if obj_b uses
...
// obj_b's function implementations
Rationale / Conditions
typedef and struct kept together
a .c file that uses obj_X must #include "obj_X.h"
to show that use
avoid .h files including other .h files in general;
only 'defs.h' files are #include'd in .h files.
avoid #include'ing a file just to handle dependencies;
IOW avoid #include'ing obj_a.h just because it's used in obj_b.h

Resources