2

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)?

user717572
  • 3,626
  • 7
  • 35
  • 60
  • take a look at this answer http://stackoverflow.com/questions/252552/why-do-we-need-c-unions "reading value from a union member to which value was not written to, is undefined behaviour by standards" – terence hill Nov 04 '15 at 23:26
  • 1
    @terencehill it is specified behavior for members of the same size: http://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified – ouah Nov 04 '15 at 23:35
  • "This should allow for statically checking whether the uninitialized member of the union is being accessed." Only sufficiently smart compilers can do that, which are rarer than unicorns. The verification is commonly done at runtime with a technique called "tagged unions" (where the union is preceded by information that unambiguously expresses which union fields were used). –  Nov 04 '15 at 23:36
  • @ouah thanks i didn't know – terence hill Nov 05 '15 at 14:57

1 Answers1

1

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).

ouah
  • 142,963
  • 15
  • 272
  • 331
  • +1, just an additional remark, the value that is written for one type, could be a trap representation of the other type. – Jens Gustedt Nov 05 '15 at 07:34
  • Assuming the `union` members are of the same size, but the one is accessed that was not last written to, wouldn't this still be undefined behaviour? – user717572 Nov 05 '15 at 18:19
  • @user717572 I explicitly say in my answer it is not UB: *this is a specified behavior and no diagnostic is required* – ouah Nov 05 '15 at 18:23