Проверка типов в постоянном анонимном союзе

Прежде всего, проверка типов не совсем правильный термин, который я ищу, поэтому я объясню: скажем, я хочу использовать анонимное объединение, я делаю объявление объединения в структуре const, поэтому после инициализации значения не изменятся. Это должно позволить статически проверять, осуществляется ли доступ к неинициализированному члену объединения. В приведенном ниже примере экземпляры инициализируются для a (int) или b (С плавающей точкой). После этой инициализации я бы не хотел иметь доступ к другому члену:

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;
}

Я хотел бы получить последние два назначения, чтобы выдать ошибку (или хотя бы предупреждение), но она не дает ничего (с помощью gcc 4.9.2). C предназначен, чтобы не проверять это, или это на самом деле недостаток языка / компилятора? Или просто глупо хотеть использовать такой шаблон?

На мой взгляд, у меня есть большой потенциал, если бы это была особенность, поэтому кто-то может объяснить мне, почему я не могу использовать это как способ различать два "подтипа" одной и той же структуры (один для каждое объединенное значение). (Потенциально есть какие-нибудь предложения, как мне все-таки сделать что-то подобное?)


РЕДАКТИРОВАТЬ: Таким образом, очевидно, что это не в стандарте языка, и компиляторы не проверяют это. Тем не менее, я лично считаю, что это было бы неплохо, так как это исключает ручную проверку unionсодержимое с использованием теговых союзов. Итак, мне интересно, у кого-нибудь есть идея, почему он не представлен в языке (или это компиляторы)?

1 ответ

Я хотел бы получить последние два назначения, чтобы выдать ошибку (или хотя бы предупреждение), но она не дает ничего (с помощью gcc 4.9.2). C предназначен, чтобы не проверять это, или это на самом деле недостаток языка / компилятора?

Это правильное поведение компилятора.

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

В первом объявлении вы инициализируете float объект с int значение и во втором вы инициализируете float объект с float значение. В C вы можете назначать (или инициализировать) любые арифметические типы любым арифметическим типам без каких-либо приведений. Так что никакой диагностики не требуется.

В вашем конкретном случае вы также читаете union члены, которые не являются теми же членами, что и union Последний член использовался для хранения его значения. Предполагая, что union члены имеют одинаковый размер (например, float а также int здесь), это определенное поведение, и никакая диагностика не требуется. Если размер union члены разные, поведение не определено (но все же, диагностика не требуется).

Другие вопросы по тегам