C make a copy of an array of const constructs

I have an array of structures and some members of the structure are constant I would like to make a deep copy of the array. The copy will also have the same structure members as the constants. How to initialize values ​​in a new array without breaking the const directive.

Below is a snippet of my code. The actual program is quite long, but I think I have included all the relevant code. In this example, the keys are declared as a global variable from which I would like to create new instances. I see it as a template with given values.

When I try to compile this on Debian with gcc I get the following error:

main.c:216:9: error: assignment of read-only location ‘*(new_keys + (unsigned int)((unsigned int)index * 540u))’make: *** [main.o] Error 1


The makefile uses the following classifier:

CFLAGS=-c -g -std=gnu99 -D_XOPEN_SOURCE=700


Interesting. I can compile the same code in Xcode without error or warning even with Xcode installed for C Language Dialect GNU99 [-std = gnu99]

I can get my code to work just by getting rid of the const keywords. But these values ​​should really be const. Once these arrays are initialized, they will never change. I would like to understand how to do this correctly, and would also like to know why this works in Xcode and not gcc.

Header file

typedef struct {
    char * name;
    char * alias;
    int number;
} pair_int_t;

typedef struct {
    const char * const name;
    const kind_t kind; // kind is enum type
    const pair_int_t * const enum_array; 
    bool received; 
    const char * const alias; 
} key_descriptor_t;

typedef key_descriptor_t keys_descriptor_t[_END_OF_KEYS+1];


c program body before main ()

const pair_int_t command_list[] = {
    {.name = "numeric data response",        .alias = "num",         .number = RES_NUMERIC_DATA},
    {.name = "read attribute",               .alias = "readat",      .number = CMD_READ_ATTR},

// declare a global variable *keys* with constants assigned to it
key_descriptor_t keys[] = {
    [_COMMAND]          = {.name = "command",           .kind = ENUMERATED, .alias = "com",    .enum_array = command_list},
    [_RESPONSE]         = {.name = "response",          .kind = ENUMERATED, .alias = "res",    .enum_array = command_list},
    [_UNIT]             = {.name = "unit number",       .kind = NUMBER,     .alias = "uni",    .enum_array = NULL},

int initialize_new_keys(keys_descriptor_t new_keys) {
    int index;
    for (index = _FIRST_KEY; index <= _END_OF_KEYS; index++){
        new_keys[index] = keys[index];      // line 216, keys is a global variable  
    return index;


main program

int main(int argc, const char * argv[]){
    keys_descriptor_t 2nd_set_of_keys;



source to share

2 answers

You can only initialize variables const

at the time they are defined. Creating an array with members const

, sending it to a function, and then trying to assign to those members means you didn't really mean it const

. There is no syntax in C for " const

other than first assignment".

A sensible alternative is to create an opaque type, encapsulate the definition in a separate translation unit, and then access all members only through the function interface. So even if things can't be const

, they still can't be changed (except for deliberate subversion, which is at least no better than not naming things const

), because no code that uses them has access to the definition, struct

or therefore to the members.

EDIT: In response to the question in the comment, "is there a way to create and initialize one complex constant variable for the value of another existing constant variable of the same type?", That is - just initialize it fine

struct mystruct {
    const int a;
    const int b;

static const struct mystruct m = {1, 2};

int main(void) {
    struct mystruct n = m;
    return 0;


Obviously, the harder yours struct

, the harder it can get.



"2nd_set_of_keys" is a structure, it must be a static array (or can be a pointer and backing memory dynamically), the same problem occurs with the "new_keys" parameter. Although a bit weird, you can copy data into constant variables (overriding constant checking) using memcpy ().



All Articles