Что такое &&& операция в C

#include <stdio.h>

volatile int i;

int main()
{
    int c;

    for (i = 0; i < 3; i++) 
    {
         c = i &&& i;
         printf("%d\n", c);
    }

    return 0;
}

Вывод вышеуказанной программы, скомпилированной с использованием gcc:

0
1
1

С опцией -Wall или -Waddress gcc выдает предупреждение:

warning: the address of ‘i’ will always evaluate as ‘true’ [-Waddress]

Как оценивается c в приведенной выше программе?


person manav m-n    schedule 19.12.2012    source источник
comment
Я полагаю, это i && (&i)? Интересно, что я не могу найти дубликат сообщения на SO.   -  person irrelephant    schedule 19.12.2012
comment
Слева направо (если не указано иное, то есть только =), поэтому &&, затем &i   -  person Voo    schedule 19.12.2012
comment
Почему вы отвечаете в комментариях, а не отвечаете на сам вопрос?   -  person Spook    schedule 19.12.2012
comment
@KennyTM: я не совсем понял while (i &&& i <-- j) {}   -  person manav m-n    schedule 19.12.2012
comment
возможный дубликат Can у вас тройной минус в программировании на Си? Что это значит?   -  person Anirudh Ramanathan    schedule 19.12.2012
comment
Не дубликат, но похожий вопрос, и это хорошая ссылка   -  person Nathan Cooper    schedule 19.12.2012
comment
@Manav stackoverflow .com/questions/1642028/   -  person Izkata    schedule 19.12.2012
comment
@LuchianGrigore Максимум жевать, это тот же ответ для &&&, +++, --- и т. д., не так ли?   -  person Anirudh Ramanathan    schedule 19.12.2012
comment
@Cthulhu, я уверен, что есть варианты лучше, чем ---, не так ли?   -  person Luchian Grigore    schedule 19.12.2012
comment
это то же самое классическое правило максимального жевания, как уже упоминал @Cthulhu. Имейте в виду, что этот вопрос снова является дубликатом, я уже нашел это однажды, но не был помечен как дубликат.   -  person aiao    schedule 19.12.2012
comment
Вы пометили вопрос gcc-warning, но не показывали предупреждение gcc (я его добавил). Вы также пометили его linux, что не имеет значения (я удалил тег).   -  person Keith Thompson    schedule 02.01.2013
comment
GCC принимает &&&&: int main(){j:return 0&&&&j;}   -  person nneonneo    schedule 30.03.2013
comment
@nneonneo, Вау. Не могли бы вы разделить это? Что оно делает?   -  person Spikatrix    schedule 05.06.2015
comment
0 && (&&j). Он использует расширение GCC для получения адреса метки j, который всегда должен оцениваться как ненулевое значение.   -  person nneonneo    schedule 05.06.2015


Ответы (2)


Это c = i && (&i);, а вторая часть избыточна, поскольку &i никогда не будет оцениваться как false.

Для определяемого пользователем типа, где вы действительно можете перегрузить унарный operator &, может быть по-другому, но это все равно очень плохая идея.

Если вы включите предупреждения, вы получите что-то вроде:

предупреждение: адрес «i» всегда будет оцениваться как «true»

person Luchian Grigore    schedule 19.12.2012
comment
Почему бы и нет : c = i & (&&i);; Где i какой-то ярлык? - person anishsane; 20.12.2012
comment
@anishsane i определяется как int, и в вопросе нет ярлыков. Кроме того, максимальный жевательный... - person Luchian Grigore; 20.12.2012
comment
@anishsane: И оператор && для получения адреса метки в любом случае является нестандартным расширением gcc. Но даже если бы он был стандартным, правило максимального манча предотвратило бы его разбор таким образом (если вы не вставите пробел). - person Keith Thompson; 28.12.2012
comment
Фактически, &i может оцениваться как false. Иногда используется для значений по умолчанию. Пример: void fn(type& x = *reinterpret_cast<type*>(NULL)); Каково значение &x в fn, если fn вызывается без параметров? Это 0 или ложь. Однако, используя его так, как описано, он всегда будет истинным, если только не i == 0, а если бы кто-то использовал его, как я описал, это было бы c = &i && i. - person Adrian; 25.05.2013
comment
@ Адриан, вы не можете разыменовать нулевой указатель, что и делает * перед reinterpret_cast<type*>(NULL). - person Luchian Grigore; 25.05.2013
comment
@LuchianGrigore: хотя тип разыменован, это не ошибка, пока значение не будет получено. Это мое понимание. Определено ли иное в стандарте? - person Adrian; 25.05.2013
comment
@ Адриан, не о чем говорить. Разыменование указателя NULL является поведением undefined. - person Luchian Grigore; 25.05.2013
comment
давайте продолжим обсуждение в чате - person Adrian; 25.05.2013
comment
Я исправляюсь. void fn(type& x = *reinterpret_cast‹type*›(NULL)); является недействительным. - person Adrian; 25.05.2013
comment
Существует заблуждение: УБ != неверный. UB означает спецификацию языка. не определяйте его, но может реализовать компилятор. И есть компиляторы, которые позволяют int& a = *(int*)0; и демонстрируют именно такое поведение (&a == nullptr). Конечно, такой код не является переносимым (на самом деле он специфичен для компилятора), но утверждение &i всегда истинно, неверно: будучи UB, оно может быть ложным. Этого никто не дает, но может быть. - person Emilio Garavaglia; 27.07.2014
comment
@EmilioGaravaglia следует предполагать, что любые утверждения о поведении фрагмента кода (если только UB уже не существует, и в этом случае может произойти что угодно) подразумеваются. - person M.M; 03.06.2015

В C нет оператора или токена &&&. Но существуют операторы && (логическое «и») и & (унарный адрес или побитовое «и»).

По правилу максимального количества пищи это:

c = i &&& i;

эквивалентно этому:

c = i && & i;

Он устанавливает c в 1, если оба i и &i истинны, и в 0, если одно из них ложно.

Для int любое ненулевое значение является истинным. Для указателя любое ненулевое значение является истинным (и адрес объекта всегда ненулевой). Так:

Он устанавливает c в 1, если i не равно нулю, или в 0, если i равно нулю.

Это означает, что &&& используется здесь только для преднамеренного запутывания. Задание также может быть любым из следующих:

c = i && 1;
c = !!i;
c = (bool)i;          // C++ or C with <stdbool.h>
c = i ? 1 : 0;        /* C */
c = i ? true : false; // C++
person Keith Thompson    schedule 19.12.2012