marmistrz
marmistrz

Reputation: 6414

Initialize a struct with data from an array

I'd like to keep my keywords in a struct:

typedef const char* label;
const struct keywords_t
{
    label init;
    label moveUnit;
} keywords;

But I'd like to be able to check whether a keyword is valid with a for loop, so I tried to initialize the struct like this:

const label allowed_keywords[] =
{
    "INIT",
    "MOVE"
};

const struct keywords_t keywords =
{
    allowed_keywords[0],
    allowed_keywords[1]
};

This gives me an

error: initializer element is not constant

What am I doing wrong? The whole array is constant, though.

Upvotes: 0

Views: 102

Answers (2)

Myst
Myst

Reputation: 19221

I might be the best resource for this, but both Arrays and Structs are simple memory mapping tools.

An array of char * and a struct containing the same number of char * should have the same memory structure and the same memory footprint.

So, in practice, all you need is to cast the array into the struct rather then anything else (this will also save you memory, although this is probably not so important).

i.e.

const label allowed_keywords[] =
{
    "INIT",
    "MOVE"
};

typedef const char* label;
const struct keywords_t
{
    label init;
    label moveUnit;
};

// struct keywords_t * keywords = (struct keywords_t *) allowed_keywords;

#define keywords ((struct keywords_t *) allowed_keywords)

A few things:

  1. this needs to be tested.

  2. I would avoid using the _t for the struct keywords_t, as _t is reserved for POSIX types. I use _s for structs and _pt for pointers... but that's up to you.

Upvotes: 1

user694733
user694733

Reputation: 16047

In C constvariables are not constants, they are simply variables that cannot be changed. Thus their value cannot be used in constant expressions, like in struct initializer.

One work-around could be to use preprocessor defines for initializers:

#define KEYWORD_INIT   "INIT"
#define KEYWORD_MOVE   "MOVE"

const label allowed_keywords[] =
{
    KEYWORD_INIT,
    KEYWORD_MOVE
};

const struct keywords_t keywords = 
{
    KEYWORD_INIT,
    KEYWORD_MOVE
};

Other approach could be to use combination of enumeration and array:

typedef enum {
    KEYWORD_INIT,
    KEYWORD_MOVE
} label;

const char * const keyword_strings[] = {
    "INIT",
    "MOVE"
};

const struct keywords_t keywords =
{
    KEYWORD_INIT,
    KEYWORD_MOVE
};

// Getting keyword string would be like this:
// keyword_strings[keywords.moveUnit]

Upvotes: 7

Related Questions