Reputation: 25
I am learning C and I am having some trouble with a bit of homework I was given.
I am attempting to use a linked list that I have implemented as part of one header inside of another header. My implementation of the list includes a typedef
that looks like this:
typedef struct queue_T
{
int count;
struct member_T * first;
struct member_T * last;
} * queue_T;
The above typedef
is inside of one source file (.c
). I am currently attempting to write a second source file that makes use of this type. Inside this source file, I attempted to declare some queue_T
variables for use as global variables. I did so like this:
#include <math.h>
#include "mathfns.h"
#include "queue.h"
queue_T primes;
queue_T squares;
queue_T cubes;
primes = new_queue();
squares = new_queue();
cubes= new_queue();
new_queue()
is my initializer function for the queue_T type and mathfns.h
is the header file associated with the source file that you're looking at immediately above this paragraph. The above declarations of queue_T variables are defaulting to integers when I attempt to compile and when I attempt to initialize the variables it is generating an error. How can I avoid this? Should I #include
the"queue.h
header in the mathfns.h
file
Thank you.
Upvotes: 1
Views: 1259
Reputation: 181034
As I wrote in comments, you cannot perform function calls outside a function. You cannot even execute assignment statements outside a function, though you can provide constant initializers for global variables, and the syntax resembles an assignment statement. Initializers are not executable, however -- they are handled by the system outside the scope of program execution (which you can take as a reason for why you cannot perform function calls in them).
Presumably, function new_queue()
both allocates a new struct queue_T
and initializes it, then returns a pointer to the caller. That's fine and useful, but what if you just want to initialize an existing struct queue_T
structure? Indeed, if you want to provide pre-initialized global objects of that type, such a facility is exactly what you need. For example:
static struct queue_T primes_struct = { 0, NULL, NULL };
queue_T const primes = &primes_struct;
/* ... */
But writing a literal structure initializer like that is tedious and error-prone. After all, what if the structure definition is changed after that code is written? In fact, if you simply want to initialize all members of a struct
to zero / NULL, the conventional form of the initialzer is just { 0 }
(a single element). But even that can end up not being what you want under some modifications.
An alternative would be to have your queue.h
declare a macro that can be used to initialize an empty struct queue_T
, and use that everywhere (including in function new_queue()
, so as to be certain the same initialization is performed everywhere). Thus, somewhere in queue.h
you might have ...
#define EMPTY_QUEUE { 0, NULL, NULL }
... and in mathfns.c
you could do this:
static struct queue_T primes_struct = EMPTY_QUEUE;
queue_T const primes = &primes_struct;
That way, if ever you modify struct queue_T
, you can make a corresponding change to the macro instead of modifying any code in source files that simply use that structure.
Upvotes: 3