TimFinnegan
TimFinnegan

Reputation: 613

How to use an extern union array in C?

I want to use a union array similar to that one chux suggested

union {
  uint8_t u8[12];
  uint16_t u16[6];
} *array_u;

array_u = calloc(1, sizeof *array_u);
assert(array_u);

printf("array_u->u8[0] = %" PRIu8 "\n", array_u->u8[0]);

array_u->u16[0] = 1234;
printf("array_u->u16[0] = %" PRIu16 "\n", array_u->u16[0]);
...

Source: Is it okay to store different datatypes in same allocated memory in C?

I want to use it as a global array that different files need to have access to it. So I tried globals.h:

extern union {
    uint8_t u8[12];
    uint16_t u16[6];
} *array_u;

And I want to allocate and free it in this file memory.c:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include "globals.h"

void allocate_array_u(void){
    array_u = calloc(1, sizeof *array_u);
}

Bud sadly I receive a error LNK2001: unresolved external symbol array_u

How can I fix that?

Solution: I forgot to define the union in main.c or memory.c:

array_u_t *array_u;

Upvotes: 4

Views: 4406

Answers (3)

user3629249
user3629249

Reputation: 16540

Suggest giving the union a 'tag' name.

union myunion 
{
    uint8_t u8[12];
    uint16_t u16[6];
};

Then on a separate statement declare an instance of a pointer to the union:

 union myunion *array_u = NULL;

then set the pointer to the union to a value:

array_u = calloc(1, sizeof union myunion);

Note: calling assert() will not tell the user what went wrong and is a poor choice in production code.

Instead, suggest:

if( NULL == array_u )
{ // then calloc failed
    perror( "calloc for instance of union myunion failed: );
    exit( EXIT_FAILURE );
}

// implied else, calloc successful

Note: placing the literal 'NULL' on the left, so a keystroke error, like typing = rather than == will be caught by the compiler rather than you spending hours and hours looking for that 'oops'.

Upvotes: 2

axiac
axiac

Reputation: 72226

You declared array_u as an external symbol in every source file that includes globals.h but where it resides? Every variable must be defined somewhere; i.e. not declared as external and, optional, initialized.

Pick the most appropriate C file and write in it:

union {
    uint8_t u8[12];
    uint16_t u16[6];
} *array_u = NULL;

You better use typedef to get a name to the union type of variable array_u to avoid defining it twice.

Write in globals.h:

typedef union {
    uint8_t u8[12];
    uint16_t u16[6];
} array_u_type;
extern array_u_type *array_u;

Write in one of the C files (memory.c, for example):

#include "globals.h"

array_u_type *array_u = NULL;

Replace in the example above array_u_type with any name you like for the new data type.

Upvotes: 1

Ziffusion
Ziffusion

Reputation: 8923

In addition to declaring array_u as extern, you also need to define the variable. extern just says to find the definition somewhere else. That definition needs to exist somewhere.

Try the following.

Change globals.h as follows:

typedef union {
    uint8_t u8[12];
    uint16_t u16[6];
} array_u_t;

extern array_u_t *array_u;

Define array_u in memory.c as follows:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include "globals.h"

array_u_t *array_u; // <---------------- definition

void allocate_array_u(void){
    array_u = calloc(1, sizeof *array_u);
}

Upvotes: 8

Related Questions