Объявление C с компиляцией самоприсваивания

Я был крайне удивлен тем, что компилируется следующий C-код:

int foo() {
    int x = x;
    return x;
}

Это гарантированно скомпилируется? Определено ли значение x после присвоения (во время тестирования в GCC оно было равно нулю)?

gcc, без оптимизации — компилируется без нареканий, неопределенное значение, gcc O3 — компилируется без нареканий и значения нулевое, clang — компилируется с предупреждением о неинициализации

teapot418 03.06.2024 21:01

Я подозреваю, что он компилируется в GCC только в том случае, если вы установили очень мягкие уровни предупреждений. Другие компиляторы C, скорее всего, вернут постоянное значение для неинициализированной переменной или ловушки времени выполнения, если они вообще будут ее компилировать. Он может скомпилироваться, но его поведение все равно будет неопределенным.

Martin Brown 03.06.2024 21:02
Думаю, clang победит
teapot418 03.06.2024 21:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Символ x справа от =, выступающий в качестве инициализатора, сам по себе не инициализирован в момент его использования. Чтение неинициализированного значения, адрес которого никогда не был взят, приводит к неопределенному поведению согласно разделу 6.3.2.1p2 стандарта C:

За исключением случаев, когда это операнд оператора sizeof, _Alignof оператор, унарный оператор &, оператор ++, оператор -- или левый операнд оператора . или оператора присваивания, lvalue, не имеющее типа массива, преобразуется в сохраненное значение. в обозначенном объекте (и больше не является lvalue); это называется преобразование значений. Если lvalue имеет уточненный тип, значение имеет неполная версия типа lvalue; кроме того, если lvalue имеет атомарный тип, значение имеет неатомарную версию тип lvalue; в противном случае значение имеет тип lvalue. Если lvalue имеет неполный тип и не имеет типа массива, поведение неопределенно. Если lvalue обозначает объект продолжительность автоматического хранения, которая могла бы быть объявлена ​​с помощью register класс хранилища (его адрес никогда не фиксировался) и этот объект не инициализирован (не объявлен с инициализатором и без присвоения если оно было выполнено до использования), поведение не определено.

Согласно этому определению, объект не является неинициализированным, поскольку он объявлен с инициализатором, поэтому тот факт, что никакое присвоение не выполнялось, не имеет значения.

Artyer 03.06.2024 21:21

@Artyer Но x еще не инициализирован на момент чтения инициализатора.

dbush 03.06.2024 21:24

Это не то, что говорится в цитате, но это кажется стандартным дефектом, потому что «неинициализированный» используется еще раз в примере 2 C2x §6.7.9 (Черновик: n3096), а double b = b*b; // undefined, uses uninitialized variable without address является примером.

Artyer 03.06.2024 21:33

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