VJune
VJune

Reputation: 1215

C array of structs initialization issues when using macros

Why is adsafe_tags[1] is not getting properly initialized?

// local string (via static)
#define SSTRL(varname, val) \
    static const char varname[] = val

#define SSTRLEN(var) \
    (sizeof(var) - 1)

struct scs_data_tag
{
    uint16_t key_size;
    uint16_t val_size;
    char     data[];
};

SSTRL(ADSAFE_KEY, "p.as.rsa");
SSTRL(ADSAFE_VAL_BAD, "0");
SSTRL(ADSAFE_VAL_GOOD, "1000");
#define ADSAFE_KV_BAD "p.as.rsa0"
#define ADSAFE_KV_GOOD "p.as.rsa1000"

struct scs_data_tag adsafe_tags[] = {
    {SSTRLEN(ADSAFE_KEY), SSTRLEN(ADSAFE_VAL_BAD), ADSAFE_KV_BAD},
    {SSTRLEN(ADSAFE_KEY), SSTRLEN(ADSAFE_VAL_GOOD), ADSAFE_KV_GOOD}
};

and in gdb I get this:

(gdb) p adsafe_tags
$7 = {{key_size = 8, val_size = 1, data = 0x8ce664 <adsafe_tags+4> "p.as.rsa0"}, {key_size = 11888, val_size = 29537, data = 0x8ce668 ".rsa0"}}

Upvotes: 3

Views: 676

Answers (2)

interjay
interjay

Reputation: 110202

You have not specified the size of the data member of struct scs_data_tag. This declares a C99 flexible array member. This member has size 0 by default, and you'd need to malloc more than the actual struct size in order for it to be able to contain data.

According to the standard, it should not be possible for struct scs_data_tag to be an element of an array (because it contains a flexible array member). But this is supported by some compilers as an extension.

If you instead give this array a large enough size (e.g. char data[40]), your code should work.

Upvotes: 2

0xF1
0xF1

Reputation: 6116

Adding to interjay's answer,. You see adsafe_tags[1].key_size = 11888 which is 0x2e70 in hex, which denotes ASCII characters p (= 0x70) and . (= 0x2e), therefore "p.".

Similarly, adsafe_tags[1].val_size = 29537, which is 0x7361 or "as", rest is printed correctly as a string.

This shows that no space is allocated to adsafe_tags[0].data.

The string you provided for initializing it got mapped to next data set.

Upvotes: 1

Related Questions