9

В this Code Golf post, есть утверждение, что «вторая переменная в определении всегда устанавливается в 1», что делает этот хорошо сформированную строку:Является ли второй int в множественном объявлении всегда равным 1?

int i=-1,c,o,w,b,e=b=w=o=c; 

И якобы все, кроме i установлен в 1, потому что c автоматически 1.

Я думал, что знаю C, и думал, что это незаконно (это UB и результат, если что-то в случайном стеке).

Действительно ли C действительно устанавливает c в 1?

+1

Я действительно не понимаю этого, 'c' присваивается неинициализированным к остальным переменным, я могу ошибаться, но, кажется, неопределенное поведение. –

+3

Согласно [this] (http://meta.codegolf.stackexchange.com/questions/5486/is-an-answer-allowed-to-use-undefined-but-consistent-behaviour), последовательное, неопределенное поведение прекрасное для игры в гольф, поэтому, возможно, создатель программы использовал это. – Downvoter

+0

Если 'i' имеет время автоматического хранения, это хорошо сформировано. Если это статическая продолжительность хранения, она неверна, поскольку для инициализации переменных необходимы постоянные выражения. – Downvoter

ответ

5

Я - ОП от CodeGolf. Кажется, у меня просто была опечатка, я хотел сказать int i=-1,c,o,w,b,e=b=w=o=c=1; Таким образом, второй определенный int всегда установлен в 1, а остальные могут быть установлены на него. Смущение в том, что у меня первоначально была переменная, которая следующая (L = 3), как только l (неопределенная), и я устанавливал все остальные переменные в e = b = w = o = c = (L = 3); который, по моему мнению, собирался установить L равным 3, верните true для этого (1), затем установите остальное на 1.

Несколько тестов позже я понял, что это просто установило их все на 3 и работало только с определенную строку, которую я использовал для проверки моего кода. Поэтому я удалил их и изменил его, чтобы быть L = 3 жестко закодированным, а остальные - e=b=w=o=c=1;L=3. В какой-то момент я должен был нажать cmd + z один раз и удалить «=» и «1», чтобы я остался только с e=b=w=o=c;. Из-за последовательного неопределенного характера этого (по крайней мере, на моей IDE) он всегда определял их как 0, и поэтому ошибка не замечалась.

Теперь, когда я исправил его, благодаря этому сообщению длина байтов такая же, и в любом случае не было необходимости в каком-либо из этого сложного кода e=b=w=o=c=1, я думал, что длина байта была иной, потому что когда я копирую вставив мою функцию в счетчик байтов, она показала, что она меньше на 2 байта (я не знал, что у меня только что была опечатка и отсутствовала 2 байта).

My IDE всегда определяет эти переменные как 0. Мой код предназначен для работы со всеми переменными, определенными как 1, тот факт, что он работает w/0, является совпадением. Также только потому, что это происходит на моей IDE, это не значит, что это будет на других, хотя я тестировал его на нескольких IDE сейчас в сети и запускал много циклов, и он, кажется, всегда return 0. В любом случае, я по-прежнему обновлял мой исходный код, чтобы установить их в 1, как и должно быть (добавив 2 байта в мою программу).

Спасибо за вход каждого

+3

С такими вопросами вы ожидаете ответа по строкам «Это UB, сожгите того, кто написал этот код на алтаре стандартного C++» или «Это потрясающий трюк, раскрывающий темный угол C++». И тогда вы пришли и были похожи на «Привет, ребята, так ... да, я сделал ошибку CTRL-Z ...», которая ... довольно разочаровывает ... о, хорошо. Бывает :) – bolov

5

Этот код показывает undefined behavior.

Переменные c, o, b и w неинициализированы. Это означает, что их содержимое является неопределенным.

Из раздела 6.7.9 в C standard:

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

Неопределенное значение c затем присваивается нескольким другим переменным. Читая значение неинициализированной переменной, код вызывает неопределенное поведение.

Начальная величина cможет быть быть 1, но если это не предсказуемое значение.

отметить также, что приведенное выше утверждение содержит как инициализация (для i и e) и назначения (для c, o, b и w), так что это заявление не будет скомпилирован в области файла.

Я попытался запустить функцию в связанном сообщении и не прошел первый тестовый ввод. Неопределенное поведение.

2

В стандарте C такого магического правила нет, этот второй объект int должен быть установлен с 1. Фактически, значение является неопределенным, и в этом случае код вызывает безусловный UB.

C11 § 6.3.2.1/2 Lvalues, массивы и функция десигнатор

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

Но давайте предположим иначе на короткое время. Вот только одна примерная сборка, созданная для архитектуры x86-64 на GCC 6.3, отключенная оптимизация, SysV ABI соглашения о вызовах:

mov  DWORD PTR [rbp-4], -1 
    mov  eax, DWORD PTR [rbp-8]  ; ??? 
    mov  DWORD PTR [rbp-12], eax 
    mov  eax, DWORD PTR [rbp-12] 
    mov  DWORD PTR [rbp-16], eax 
    mov  eax, DWORD PTR [rbp-16] 
    mov  DWORD PTR [rbp-20], eax 
    mov  eax, DWORD PTR [rbp-20] 
    mov  DWORD PTR [rbp-24], eax 

Что касается, так как компилятор обеспокоен, нет ни никаких гарантий. Переменная c расположена на текущем стеке кадра при RBP-8 смещении. Его начальное значение - . хранилось ранее в стеке.

+1

Это _one_ возможность неопределенного поведения. Но это не определено, поэтому ваша программа может потерпеть крах, или все переменные установлены на разные значения, или все переменные остаются неопределенными с большей увлекательностью позже в вашей программе. – gnasher729