简体   繁体   中英

Initializing a nested struct with const members

I have the following types, for illustration:

struct outer {
  struct inner {
    const int c;
    int x;
  } i;
  int y;
};

I want to malloc outer and then, later, initialize inner to get the right const behavior for outer.ic .

For example, something like

struct outer *o = malloc(sizeof *o);
o->y = find_y();
int cc = find_c();
int xx = find_x();
o->i = { .c = cc, .x = xx };

but this gives me an error about assignment of read-only member 'i' , because it's an assignment, not an initialization.

Is there a way to do something like this that's up-front to the compiler? Let's consider tricks like casting away const with *((int *) &o->ic) or using memcpy on &o.i as sneaking around the compiler. I can get the bits where they need to be, but I am looking for the least sneaky way to do this.

I am not using C++ (I'm using C99).

The only really constant things are things residing in read-only memory. Malloc/calloc will never give you read-only memory. So that "const" there is a lie. Well, it is a hint for compiler(s) and to developer(s). I am not sure if there are any syntax sugars in C99 to address something that might seem an issue to someone, but here is how I would do it:

#include <stdio.h>
#include <stdlib.h>

struct outer {
    struct inner {
        const int c;
        int x;
    } i;
    int y;
};

int main(void)
{
    struct outer    *o;

    o      = calloc(1, sizeof(struct outer));

    printf("before: %d %d %d\n", o->i.c, o->i.x, o->y);

    *((int *)&o->i.c) = 1;
    o->i.x = 2;
    o->y = 3;

    printf("after: %d %d %d\n", o->i.c, o->i.x, o->y);

    return 0;
}

Please take into account that this is a more practical solution than academic, thus some people might want to throw a few rotten eggs at me for it.

I would probably do this:

struct outer_init {
  struct inner_init {
    int c;
    int x;
  } i;
  int y;
};

struct outer_init *oi = malloc(sizeof *oi);
oi->y = find_y();
oi->i.c = find_c();
oi->i.x = find_x();

struct outer *o = (struct outer *)oi;

I am not completely sure that it is absolutely portable though.

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