gietljohannes
gietljohannes

Reputation: 305

What's the difference between these C external definitions?

I ran into this problem debugging an AVR microcontroller: I have a main.c file with numerous variable definitions, amongst them an array of structs, like this:

struct mystruct mystruct_array[COUNT];

In another .c file I refer to this array as external, but I left away the array brackets and size so I wouldn't repeat myself and just declared the variable as a pointer (because arrays are essentially pointers, aren't they?):

extern struct mystruct *mystruct_array;

But when I checked the address of the array using printf("%p\n", mystruct_array);I got a null pointer instead of the array's location in memory. Also if I would access the subsequent items in the array, like printf("%p\n", &(mystruct_array[n])); it would print address 0 plus n times sizeof(struct mystruct).

Only after I changed the definition to

extern struct mystruct mystruct_array[COUNT];

(exactly the same as in main.c), I got the true address of the array.

My question: Why does this make a difference to the compiler (in my case avr-gcc)?

Upvotes: 3

Views: 425

Answers (3)

tux3
tux3

Reputation: 7320

That's a fun one.

When you write :

struct mystruct mystruct_array[COUNT];

You create a global array of mystruct structs, there are COUNT of them, and since you didn't initialize it, it'll be filled with zeros.

When you then write:

extern struct mystruct *mystruct_array;

You tell the compiler that there's a variable called mystruct_array somewhere and that it's a pointer. But it's not, it's an array. So the compiler is going to read the content of the array as if it were a pointer.

So when you try to output the value of that pointer, the compiler goes fetch mystruct_array in memory and outputs its content as if it were a pointer. Since it's actually an array full of zeros, you're seeing a null pointer in the output.

Instead you should write something like:

extern struct mystruct mystruct_array[];

So the compiler knows the correct type of your variable. You can specify the length in the square brackets here, but you don't have to.

I'd recommend you go read up on the differences between pointers and arrays to make sure you don't confuse them in the future.

Upvotes: 8

Sir Jo Black
Sir Jo Black

Reputation: 2096

The declaration of extern means that the declared object is global in an other C file. Then, when you generate the object file, it is generated also if the declared object (in this case the structure) is not present.

If you declare:

extern struct structname * s;

means that in the other C module there's a global visible pointer to a structure structname s.

If you declare:

extern struct structname s;

means that in the other C module there's a global visible structure structname s!

When you will link the program, if you don't indicate to the linker to link the object that contains the structure, you will get an Undefined reference!

Upvotes: 0

John Bollinger
John Bollinger

Reputation: 180351

The ideal way to do this is to put an extern declaration in a header file, and a definition in exactly one file. For example,

header.h

extern struct mystruct mystruct_array[];
/* or extern struct mystruct mystruct_array[COUNT] */

main.c

#include "header.h"

#define COUNT 10
/* should have an initializer to be a definition: */
struct mystruct mystruct_array[COUNT] = { 0 };

/* ... */

other.c

#include "header.h"

/* ... */
    printf("%p\n", mystruct_array);

That saves you repetition, and limits the places where you might need to make changes. Note that if your header does not define the number of elements in the array, then you cannot apply the sizeof operation to that array in files other than the one that also provides the array definition.

Note, too, that although arrays are not pointers, in most contexts in C source code, an array name is converted to a pointer to the first element of the array. This is the source of the misapprehension that arrays are pointers. Although they are not pointers, in many ways they act as if they were.

Upvotes: 2

Related Questions