C - emulate "mutable" from C ++

I have a C structure like this:

struct my_struct {
   int i;
   double d;
   struct expensive_type * t;
};

An instance of this structure is created and initialized as:

struct my_struct * my_new( int i , double d) 
{
    struct my_struct * s = malloc( sizeof * s);
    s->i = i;
    s->d = d;
    s->t = NULL;
    return s;
}   

Computing a member is struct expensive_type * tquite expensive and may not be needed - for this, it is simply initialized to NULL- and later calculated by request:

const struct expensive_type * my_get_expensive( const struct my_struct * s) 
{
    if (!s->t)
       s->t = my_expensive_alloc( s->i , s->d );
    return s->t;  
 }

In C ++, I would use mutablein an element struct expensive_type *whether it is possible to achieve something similar in C, that is, drop the constant locally:

{
    struct my_struct * mutable_s = (struct my_struct*) s;
    mutable_s->t = ...;

}

Or removes constmy only standard alternative in the signature?

+6
source share
1 answer

You can (1) change the structure of the code and add an indirect layer:

struct expensive; // Forward declaration, ignore
// One could also use a struct expensive * (a pointer) instead
// of this structure. IMO giving it a name is the better option.
struct expensive_handle {
  struct expensive * target;
};

// Store the simple data members as usual, store a pointer to a
// handle (pointer) to the expensive ones
struct my_struct {
  int simple;
  struct expensive_handle * handle;
};

struct expensive {
  int content; // whatever
};

my_struct /, :

struct my_struct * new() {
  struct my_struct * data = malloc(sizeof(*data));
  // Error handling please
  // Set simple data members
  data->handle = malloc(sizeof(*(data->handle)));
  // Error handling please
  data->handle->target = NULL;
  return data;
}

target ( ) NULL.

(, , , ) const my_struct, my_struct:

int get_expensive(struct my_struct const * ptr) {
  if (ptr->handle->target == NULL) {
    ptr->handle->target = malloc(sizeof(struct expensive));
    // Error handling please
    puts("A hell of a computation just happened!");
    ptr->handle->target->content = 42; // WOO
  }
  return ptr->handle->target->content;
}

, , *(ptr->handle), a struct expensive_handle. ( handle).

(Live on ideone):

int main(void) {
  struct my_struct * p = new();
  printf("%d\n", get_expensive(p));
  printf("%d\n", get_expensive(p));
}

(1) , ( , ), .

+2
source

Source: https://habr.com/ru/post/1017119/


All Articles