Тернарный оператор как команда?

в исходный код для nanodns, есть нетипичное использование троичного оператора в попытке уменьшить размер кода:

/* If the incoming packet has an AR record (such as in an EDNS request),
* mark the reply as "NOT IMPLEMENTED"; using a?b:c form to save one byte*/
q[11]?q[3]|=4:1;

Не очевидно, что делает эта строка. На первый взгляд, похоже, что он присваивает значение одному из двух элементов массива, но это не так. Скорее, он либо выполняет элемент массива, либо ничего не делает (запускает команду). 1).

Похоже, что он должен быть заменой этой строки кода (которая действительно на один байт длиннее):

if(q[11])q[3]|=4;

Буквальный эквивалент будет следующим:

if (q[11])
q[3]|=4;
else
1;

Тернарный оператор обычно используется как часть выражения, поэтому его использование в качестве отдельной команды кажется странным. В сочетании с, казалось бы, не к месту 1эта строка почти квалифицируется как запутанный код.

Я провел быстрый тест и смог скомпилировать и запустить программу на C (++) с константами данных как «команда», например void main() {0; 'a'; "foobar"; false;}, Это кажется своего рода команда NOP, но я не могу найти никакой информации о таком использовании —Google не очень поддается к этому тип поиск запрос).

Может кто-нибудь объяснить точно, что это такое и как это работает?

3

Решение

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

«В крошечных C-программах принято определять повторно используемые выражения
сделать код меньше

завершено b *** s ***. Это утверждение, где вещи начали идти ужасно неправильно.

Размер исходного кода не имеет никакого отношения ни к размеру исполняемого файла компилятора, ни к какому-либо отношению к потреблению памяти этого исполняемого файла, ни к производительности программы. Единственное, на что это влияет — это размер файлов исходного кода на компьютере программиста, выраженный в байтов.

Если вы не программируете на компьютере 8086 середины 80-х годов с очень ограниченным пространством на жестком диске, вам никогда не нужно «уменьшать размер кода». Вместо этого пишите читаемый код.

Как говорится, так как q является массивом символов, код, который вы связали, эквивалентен

if(q[11])
{
(int)(q[3] |= 4);
}
else
{
1;
}

куда 1 это утверждение без побочных эффектов, оно будет оптимизировано. Он был размещен только потому, что ?: Оператор требует третьего оператора.

Единственная разница между утверждениями if и ?: Оператор тонкий: ?: неявно балансирует тип между 2-м и 3-м операндом.

Чтобы повысить удобочитаемость и создать самодокументированный код, код должен быть переписан в нечто вроде

if (q[AR_INDEX] != 0)
{
q[REPLY_INDEX] |= NOT_IMPLEMENTED;
}

Как примечание, здесь есть ошибка: q[2]|=128;, q имеет тип char, который имеет подпись, определяемую реализацией, поэтому эта строка потенциально катастрофична. Основная проблема заключается в том, что вы никогда не должны использовать char тип для побитовых операций или любой другой арифметики, которая является классической ошибкой новичка. Должен быть заменен на uint8_t или же unsigned char,

2

Другие решения

В C и C ++ любое выражение может быть превращено в утверждение путем ; в конце.

Другим примером является то, что выражение x = 5 можно сделать в виде заявления: x = 5; , Надеюсь, вы согласны, что это хорошая идея.

Это излишне усложнит язык, чтобы попытаться «запретить» некоторое подмножество выражений ; следуй за ними Этот код не очень полезен, но он законен.

5

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector