简体   繁体   中英

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;

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);
}

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; ie 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM