ASCIIhex4D
ASCIIhex4D

Reputation: 25

How can I use a typedef struct from one module as a global variable in another module?

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

Answers (1)

John Bollinger
John Bollinger

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

Related Questions