Reputation: 613
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
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
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
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