Defining self-referential structs in a C header file (.h)? - c

I'm trying to create a struct used in two .c source files to make a simple linked list structure. I thought it would save time to create a struct in the header file, however, I get a 'parse error before *' error.
This is the code I'm using:
/*
* Structures.h
*
* Created on: Dec 17, 2011
* Author: timgreene
*/
#ifndef STRUCTURES_H_
#define STRUCTURES_H_
typedef struct list_struct {
int data;
struct list_struct* next;
struct list_struct* prev;
} list;
#endif /* STRUCTURES_H_ */
Edit: I did originally omit a detail that is, I'm actually compiling with xcc from the XMOS toolchain. I still don't understand that there would be a difference in .h file syntax.
Could it be a compilation flag I'm using?
Here's the console printout:
xcc -O0 -g -Wall -c -MMD -MP -MF"filter.d" -MT"filter.d filter.o " -target=XC-1A -o filter.o "../filter.xc"
In file included from ../filter.xc:15:
Structures.h:13: error: parse error before '*' token
Structures.h:14: error: parse error before '*' token
Structures.h:15: error: parse error before '}' token

Looking around in some of the XMOS documentation, it seems the problem is that XC is not C, it's just a C-like language. From the "XC Programming Guide":
XC provides many of the same capabilities as C, the main omission being support
for pointers.
...which explains why it doesn't accept the next and prev pointers in your structure.
Apparently xcc lets you mix C and XC sources, though, so if you were to limit your use of the structure to C code it should work. From the "XCC Command-Line Manual", it appears that anything with a .xc extension (as in the command line you used above) is treated as XC, rather than C, source code by default. This can be overridden by placing the option -xc before the C sources on the command line and -x afterward (or just rename the files with a .c extension).
If you must use XC rather than C, you may need to find another way of doing things (arrays, maybe?).

Try using a forward declaration of struct list_struct:
struct list_struct;
typedef struct list_struct {
int data;
struct list_struct* next;
struct list_struct* prev;
} list;
Perhaps your compiler doesn't recognize the identifier in the middle of its own definition, I'm not sure what the standards say about that (if anything).
For those that don't already know, this is also the way to deal with circular dependencies in struct definitions:
struct a;
struct b;
struct a {
int x;
struct b *y;
};
struct b {
int x;
struct a *y;
};

Related

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.

malloc a struct in kernel header file error :invalid application of 'sizeof' to incomplete type

I'm new to linux.
I'm practice syscall and I want to copy struct to user.
So I write a syscall which is using copy_to_user().
But When I write and compile test.c to test my syscall appear some error.
in linux/sched.h has defined:
struct pacct_struct {
int ac_flag;
long ac_exitcode;
unsigned long ac_mem;
cputime_t ac_utime, ac_stime;
unsigned long ac_minflt, ac_majflt;
};
and then I write a program that use this struct(test.c)
#include "linux/sched.h"
#include <stdlib.h>
int main(){
struct pacct_struct *ts;
ts = (struct pacct_struct *)malloc(sizeof(struct pacct_struct));
return 0;
}
and gcc show the follow error message:
test.c:6:44: error: invalid application of 'sizeof' to incomplete type 'struct pacct_struct'
I wonder to know if it's fine to use kernel struct by include header file.
If so, do I miss something? How to make pacct_struct become a 'complete type'?
thanks.
addition:
I check preprocessor with gcc -E
I found that seems no "struct pacct_struct" being included.
Next, I going to view sched.h that I included which was created by "make headers_install" after I compile the kernel.
The file only contains some cloning flags such like "#define CSIGNAL 0x000000ff"
So, I tried to include original source file of sched.h in dir "/usr/src/linux-2.6.39.4/include/linux", but it continue showing same error 'incomplete type'.
Then I check preprocessor again.
I still can't find 'struct pacct_struct' even I include original header file
Anything in sched.h after #ifdef __KERNEL__ is disappear, What happened?

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).

libwebsockets: Dereferencing pointer to incomplete type error

I'm using libwebsockets and I can't compile a demo code implemented by myself.
I created the context:
struct libwebsocket_context *context;
...
context = libwebsocket_create_context(&info);
and when I try to access the members of the struct libwebsocket_context, defined in private-libwebsockets.h:
struct libwebsocket_context {
struct pollfd *fds;
struct libwebsocket **lws_lookup; /* fd to wsi */
int fds_count;
int max_fds;
int listen_port;
...
};
For example,
printf("%d\n", context->listen_port);
The compiler returns,
error: dereferencing pointer to incomplete type
Thanks!
It seems that "struct libwebsocket_context" is not known for gcc - that's why this error occures. Are you sure that definition of this structure is included from .h file? I'd suggest you to insert for example #warning or #error with some message near definition of this struct (in .h file) and try to recompile your program. Your #error or #warning message should appear while compilation. If not - it means that gcc will not also see this struct.
The fact that the struct definition is in private-libwebsockets.h suggests that you are not supposed to use the struct members directly. You can #include that header to get access to the private implementation details of the library but you probably should not do it.

How to use multiple source and header files

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.

Resources