Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
like image 665
TimFinnegan Avatar asked Dec 18 '22 20:12

TimFinnegan


2 Answers

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);
}
like image 153
Ziffusion Avatar answered Jan 04 '23 21:01

Ziffusion


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

like image 39
user3629249 Avatar answered Jan 04 '23 21:01

user3629249