简体   繁体   中英

Does it make any sense to make struct immutable?

Since I came to C from higher level Java where we don't have type quialifiers like const in order to make a type immutable we have to declare all its members final and be sure the members are immutable by themselves.

By contract, in C we have type quialifier const .

To be more specific, let me provide an example I'm currently stuck with. I have the following

application.h :

struct application_config_t{
    int poll_interval;
    int compression_ratio;
    //other config parameters
};

struct application_t{  //This structure make me confused
    void (*run_application)(struct application_t*);
    void (*stop_application)(struct application_t*);
};

struct application_t* create_app(const struct application_config_t);
void release_app(struct application_t*);

I'm not sure about how to define application_t structure. Its only purpose is to do the actaul run with run_application and to handle SIGINT with stop_application to perform graceful shutdown and then after stop_application returns to call release_app(struct application_t*) to free the memory.

I have the following case to choose:

I . Immutable application_t

struct application_t{
    void (*const run_application)(struct application_t*);
    void (*const stop_application)(struct application_t*);
}

I think this is fine because once created an application should not be modified. But creation of such an immutable structure will entail memcpy call anyway...

II . Mutable application_t while create application will be declared as

const struct application_t* create_app(const struct application_config_t);

This would be fine, but I want to release the memory pointed to by struct application_t* after stop_application returns. Releasing struct application_t* means that appliaction_t is not really const . And usage like

struct application_config_t cfg;
//...
const struct application_t *app_ptr = create_app(cfg);
(app_ptr -> run_application)(app_ptr);
release_app((struct application_t *) app_ptr); //const cast

would require cast against const ness.

Releasing struct application_t* means that appliaction is not really const

Actually it is. The client code could not mutate it, and should not be using it further after handing it over to release_app anyway. It is const throughout its lifetime, and if release_app accepts by a pointer to const, it will be semantically correct (just do the cast inside release_app ).

Why do I say it will be semantically correct? Because when create_app allocates space for the structure and initializes it, it isn't const in there, is it? The const is added later as part of a contract. So accepting a const pointer in release_app is just following the same contract you already established. The fact the API pair knows the storage can be mutated doesn't break the contract.

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