где мясо и картошка в

вопрос касается определенности или иного назначения неинициализированной автоматической переменной другой переменной того же типа.

Рассмотреть возможность

typedef struct
{
    int s1;
    int s2;
} Foo;

typedef union
{
    int u1;
    Foo u2; 
} Bar;

int main()
{
    {
        int a;
        int b = a; // (1)
    }
    {
        Foo a;
        Foo b = a; // (2)
    }
    {   
        Bar a;
        a.u1 = 0;
        Bar b = a; // (3)
    }
}

Ссылаясь на комментарии вmain:

(1) не определено, так какa неинициализирован. Это много я знаю.

Но как насчет (2)? Члены структурыs1 а такжеs2 неинициализированы.

Кроме того, как насчет (3)? Память u2.s2 неинициализирована, поэтому чтение ее - неопределенное поведение, нет?

 bolov22 нояб. 2017 г., 12:09
 Frank AK22 нояб. 2017 г., 10:29
Пытатьсяvalgrind ./a.out , вы увидите, что вам нужно знать.
 Jean-François Fabre22 нояб. 2017 г., 10:33
неопределенное поведение, потому что вы не можете знать значения (автоматические переменные). но, конечно, это безопасно: это ничего не делает, если вы не используете их для чего-то полезного ...
 user237152422 нояб. 2017 г., 11:04
Я думаю, что этот третий пример заслуживает тег language-lawyer, поэтому я добавляю его. Я почти уверен, что он четко определен, как я написал в своем ответе, но давайте посмотрим.
 linuxfan22 нояб. 2017 г., 10:29
Я думаю, что естьнет неопределенное поведение. Но неинициализированные данные, да. Поэтому: да, вы можете написать эти задания, они законны, они бесполезны.

Ответы на вопрос(2)

Решение Вопроса

В соответствии со стандартом C значение объекта с автоматической продолжительностью хранения, которое не инициализировано, равнонеопределенный (C 2011 [N1570] 6.7.9 10). Номинально это означает, что оно имеет определенную ценность, но мы не знаем, что это такое, когда пишем программу.

Тем не менее, стандарт также гласит: «Если lvalue обозначает объект автоматической длительности хранения, который мог быть объявлен с помощьюрегистр класс хранилища (никогда не брали его адрес), и этот объект не инициализирован (не объявлен с помощью инициализатора, и до него не было выполнено присвоение ему), поведение не определено »(6.3.2.1 2). В вашем примере кода адресa никогда не берется и не инициализируется, а использование его в выражении является lvalue. Следовательно, поведение не определено.

(Этот отрывок, 6.3.2.1 2, был разработан, чтобы приспособить процессоры, которые могут обнаружить использование неинициализированного регистра. Тем не менее, правило в стандарте C применяется ко всем реализациям.)

(3) не четко рассматривается в стандарте C. Хотя члену объединения было присвоено значение, и, следовательно, он не инициализирован для целей 6.3.2.1 2, объект, используемый вb = a это союз, а не его член. Очевидно, что наше интуитивное представление о том, что если члену объединения присваивается значение, объединение имеет значение. Однако я не вижу этого в стандарте C.

Мы можем сделать вывод, что 6.3.2.1 2 не предназначен для того, чтобы считать объединение или структуру неинициализированными, по крайней мере, если для части из них было присвоено значение, потому что:

Структуры могут иметь неназванные элементы, такие как неназванные битовые поля.

Согласно C 6.7.9 9, неназванные члены структур имеют неопределенное значение даже после инициализации (структур).

Если 6.3.2.1 2 применяется к структурам, в которых не каждому члену было присвоено значение, тоb = a всегда будет неопределенным, еслиa были структуры с неназванным членом и имели автоматическую продолжительность хранения.

Это кажется необоснованным, а не тем, что предполагалось стандартом.

Однако здесь есть место для маневра. Стандарт мог бы указать, что структура неинициализирована, только если она была инициализирована иливсе его именованным членам были присвоены значения. В этом случае (3) будет неопределенным, еслиa были структурой, в которой только одному члену было присвоено значение. Я не думаю, что эта комната для маневра существует с союзом; если члену профсоюза было присвоено значение, разумно считать, что профсоюз не инициализирован.

 Ian Colton22 нояб. 2017 г., 11:27
Спасибо вам за это, в частности, за то, что вы нашли время для исследований (3).

неопределенное поведение, это только делает результат неуказанным.

Но код, который вы показываете, действительно имеетнеопределенное поведение - по другой причине, чем вы предполагаете. Ссылаясь на N1570 (последняя версия C11),§6.3.2.1 р2 Вот:

[...] Если lvalue обозначает объект автоматического хранения, который можно было бы объявить с помощьюregister класс хранилища (никогда не брали его адрес), и этот объект не инициализирован (не объявлен с помощью инициализатора, и до него не было выполнено присвоение ему), поведение не определено.

Объясняя это немного: стандарт C подготовлен для обработки значений, которые не хранятся вадресуемое местоположение, Обычно это тот случай, когда они хранятся в одном из регистров процессора. Явно давая объектregister класс хранения является тольконамек компилятору, что он должен, если это целесообразно, хранить этот объект в регистре. С другой стороны, компилятор может содержать любой объектпродолжительность автоматического хранения в регистре, если коду не нужно обращаться к нему (с помощью указателя).

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

Если ваш код будет указатель на соответствующийa во всех этих примерах результат присваивания будет неопределенным (конечно), но поведение будет определено.

Стоит добавить, чтоstructс иunionне имеют ничего общего с ответом на ваш вопрос. Правила одинаковы для всех видов объектов с автоматическим сроком хранения. Тем не менее, в вашем третьем примере,a больше не инициализируется после назначения одного членаunion, Итак, для вашего третьего примера поведение четко определено. Неважно, что в другом членеunion,union может содержать значение только для одного из его членов одновременно.

 David C. Rankin22 нояб. 2017 г., 11:56
Я полностью согласен. Как только вы назначите одного из членов профсоюза, вы будете в порядке. Проблема в агрегатах (структурах). Вот где требуется инициализация одного члена. (ссылка на12 со словомunion в этом как раз конгломерат всех заметок12 и вне применения как к структуре, так и к объединению.19 где мясо и картошка в:)
 Eric Postpischil22 нояб. 2017 г., 11:06
... члены структуры, в которой есть неназванные участники. Так что еслиb = a может быть неопределенным, если какой-либо членa не было инициализировано, тогда структуры с неназванными членами никогда не могут использоваться в выражениях (если вы не берете их адрес).
 Eric Postpischil22 нояб. 2017 г., 11:05
Я не уверен, что 6.3.2.1 относится к (3). Я не вижу, чтобы стандарт прояснил, что означает, что структура должна быть неинициализирована в этой ситуации. Ясно, что если бы всем членам структуры было присвоено значение, мы ожидали бы, что поведение будет определено, но это не будет строго соответствовать тексту в 6.3.2.1, поскольку не было выполнено никакого присвоения объекту, который является структурой, только присваивания его члены. Но что, если только некоторые члены были назначены? Согласно 6.7.9 10, неназванные члены структуры имеют неопределенные значения даже после инициализации. Так что мы никогда не сможем дать ценности всем ...
 Eric Postpischil22 нояб. 2017 г., 11:07
К сожалению, я думал о (3) со структурой, а не с профсоюзом. (Это все еще интересный вопрос.) Позвольте мне подумать о союзе.
 user237152422 нояб. 2017 г., 11:06
@EricPostpischil Я совсем забыл рассмотреть этот примервообще, но отредактировано несколько минут назад. Он должен быть четко определен, объединение инициализируется после записи одному члену. Было бы еще интереснее спросить о структуре.

Ваш ответ на вопрос