Почему GCC не поддерживает назначение троичного расширения?
GCC имеет отличное расширение троичных выражений для C, которое позволяет нам создавать такие выражения:
int x = some_var ?: 10; // expands to some_var ? some_var : 10
Что действительно хорошо, и хотя это не особенно интуитивно понятно, оно работает. Большинство бинарных операторов в языке C имеют связанный с ними дополнительный оператор, который позволяет присваивать:
x = x + 2;
// instead, we can say
x += 2;
Так как это так, и норма для большинства бинарных операторов C (+
, -
, *
, /
, %
, |
, &
, ^
), почему это не относится к троичному оператору расширения:
int x = ...;
x ?:= 2; // error: Expected expression before '=' token
// which would expand to
x = x ?: 2;
Единственные операторы, которые не поддерживают это в стандартном C, являются логическими операторами (||
, &&
), к которому определенно троичный не подпадает, так почему мы не можем этого сделать?
Мне бы очень хотелось сделать смайлик с классной прической в моем коде, но я не могу! Был ли это упущение при проектировании оператора, или это было намеренно и где-то задокументировано? Это результат того, что оператор замкнул свой операнд или что-то еще?
1 ответ
Чтобы ответить на вопрос, я считаю, что есть и другие вопросы, на которые также нужно ответить.
Почему есть
?:
оператор на языке C и почему это лучше, чемif-else
?
Насколько я знаю, никто не смог ответить на этот вопрос, просто изложив свои субъективные мнения. K&R 2.11 утверждает, что
"Условное выражение часто приводит к сжатому коду".
а затем они иллюстрируют это с линией
printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');
что является их собственным субъективным, грязным мнением. Лично я считаю, что
printf("%6d", a[i]);
if(i%10==9 || i==n-1)
printf("\n");
else
printf(" ");
намного, намного яснее, поскольку я могу прочитать и понять этот код за 10 секунд, а не 1 минуту, чтобы прочитать и понять версию K & R. Кроме того, мой код отделяет целочисленную печать от несвязанного форматирования. Но, конечно, это мое субъективное мнение, здесь нет очевидного правильного или неправильного.
Что касается официальных источников, то обоснование C99 версии 5.10, 6.5.15 на самом деле не упоминает, зачем нужен оператор?:. В основном это просто говорит о том, что поведение оператора было изменено в новом стандарте:
Синтаксические ограничения на средний операнд условного оператора были смягчены и теперь включают в себя нечто большее, чем просто логическое выражение ИЛИ: несколько существующих реализаций приняли эту практику.
Тип выражения условного оператора может быть void, структурой или объединением; большинство других операторов не имеют дело с такими типами. Однако правила балансировки типов между указателем и целым числом были ужесточены, поскольку теперь только указатель может переноситься только на константу 0.
Так что, если у кого-то есть желание выполнить арифметику над типами struct или union, то?: Предположительно более удобна, чем if-else. Я не вижу очевидной выгоды от этого, но, по крайней мере, у оператора есть основания для его существования.
Следующий вопрос будет:
Почему существует расширение компилятора для
?:
операнд в компиляторе GCC?
Ответ на это упоминается здесь:
Когда это становится полезным, это когда первый операнд содержит, или может (если это макропараметр) содержать побочный эффект. Затем повторение операнда в середине будет выполнять побочный эффект дважды. Пропуск среднего операнда использует уже вычисленное значение без нежелательных последствий его повторного вычисления.
Так что это расширение GCC не имеет ничего общего с читабельностью или согласованностью языка, оно было просто добавлено, чтобы избежать нежелательных побочных эффектов.
Затем попытаться ответить на исходный вопрос:
Почему GCC не поддерживает назначение троичного расширения?
Возможно, потому что доступ к lvalue в условии присваивания обычно не приводит к нежелательным побочным эффектам. x = x ? : 2;
будет иметь только нежелательные побочные эффекты, если х был объявлен как volatile
- чтение изменчивой переменной является побочным эффектом. Так что единственное практическое использование, которое я могу видеть с x ?:= 2;
будет препятствовать тому, чтобы кто-то получил доступ к той же самой изменчивой переменной дважды в том же условном выражении.
И это особенность очень узкой и ограниченной ценности. Возможно, это будет полезно в каком-то особом случае встроенной системы, когда вы читаете аппаратные регистры в требовательной системе реального времени... кроме этого, я не вижу смысла в этом.
Также я не могу найти никаких официальных или канонических источников, в которых говорится о каком-либо использовании самого оператора?: Помимо традиций и субъективных предпочтений стиля кодирования.