user717572
user717572

Reputation: 3652

Typechecking in const anonymous union

First off, typechecking is not exactly the correct term I'm looking for, so I'll explain: Say I want to use an anonymous union, I make the union declaration in the struct const, so after initialization the values will not change. This should allow for statically checking whether the uninitialized member of the union is being accessed. In the below example the instances are initialized for either a (int) or b (float). After this initialization I would like to not be able to access the other member:

struct Test{
    const union{
        const int a;
        const float b;
    };
};

int main(){
    struct Test intContainer = { .a=5 };
    struct Test floatContainer = { .b=3.0 };

    int validInt = intContainer.a;
    int validFloat = floatContainer.b;

    // For these, it could be statically determined that these values are not in use (therefore invalid access)
    int invalidInt = floatContainer.a;
    float invalidFloat =  intContainer.b;

    return 0;
}

I'd hope to have the last two assignments to give an error (or at least a warning), but it gives none (using gcc 4.9.2). Is C designed to not check for this, or is it actually a shortcoming of the language/compiler? Or is it just plain stupid to want to use such a pattern?

In my eyes it looks like it has a lot of potential if this was a feature, so can someone explain to me why I can't use this as a way to differentiate between two "sub-types" of a same struct (one for each union value). (Potentially any suggestions how I can still do something like this?)


EDIT: So apparently it is not in the language standard, and also compilers don't check it. Still I personally think it would be a good feature to have, since it's just eliminating manually checking for the union's contents using tagged unions. So I wonder, does anyone have an idea why it is not featured in the language (or it's compilers)?

Upvotes: 2

Views: 159

Answers (1)

ouah
ouah

Reputation: 145839

I'd hope to have the last two assignments to give an error (or at least a warning), but it gives none (using gcc 4.9.2). Is C designed to not check for this, or is it actually a shortcoming of the language/compiler?

This is a correct behavior of the compiler.

float invalidInt = floatContainer.a;
float invalidFloat = intContainer.b;

In the first declaration you are initializing a float object with an int value and in the second you are initializing a float object with a float value. In C you can assign (or initialize) any arithmetic types to any arithmetic types without any cast required. So no diagnostic required.

In your specific case you are also reading union members that are not the same members as the union member last used to store its value. Assuming the union members are of the same size (e.g., float and int here), this is a specified behavior and no diagnostic is required. If the size of union members are different, the behavior is unspecified (but still, no diagnostic required).

Upvotes: 1

Related Questions