Два равных знака в одной строке?

Может кто-нибудь объяснить, что это делает и как это законный код C? Я нашел эту строку в этом коде: http://code.google.com/p/compression-code/downloads/list, которая является реализацией C алгоритма Vitter для Адаптивное кодирование Хаффмана

ArcChar = ArcBit = 0;

Из функции:

void arc_put1 (unsigned bit)
{
    ArcChar <<= 1;

    if( bit )
        ArcChar |= 1;

    if( ++ArcBit < 8 )
        return;

    putc (ArcChar, Out);
    ArcChar = ArcBit = 0;
}

ArcChar - это int, а ArcBit - это unsigned char

Ответы

Ответ 1

Значение выражения (a = b) - это значение b, поэтому вы можете связать их таким образом. Они также являются право-ассоциативными, поэтому все работает.

По существу

ArcChar = ArcBit = 0;

(приблизительно 1) совпадает с

ArcBit = 0;
ArcChar = 0;

так как значение первого присваивания является назначенным значением, таким образом 0.

Что касается типов, хотя ArcBit является unsigned char, результат присваивания будет расширен до int.


1 Это не совсем то же самое, поскольку, как указывает R.., в комментарии ниже.

Ответ 2

ArcChar = ArcBit = 0;

Назначение лево-ассоциативное, поэтому оно эквивалентно:

ArcChar = (ArcBit = 0);

Результат ArcBit = 0 - это новое значение, то есть - 0, поэтому имеет смысл назначить 0 на ArcChar

Ответ 3

Это просто цепочка оператора присваивания. Стандарт говорит в 6.5.16 Assignment operators:

Оператор присваивания должен иметь модифицируемое значение lval в качестве его левого операнда. Оператор присваивания сохраняет значение в объекте, обозначенном левым операндом. выражение присваивания имеет значение левого операнда после назначения, но не является именующий. Тип выражения присваивания - это тип левого операнда, если только левый операнд имеет квалифицированный тип, в этом случае это неквалифицированная версия типа левый операнд. Побочный эффект обновления сохраненного значения левого операнда должен между предыдущей и следующей точками последовательности.

Итак, вы можете сделать что-то вроде:

a=b=2; // ok

Но не это:

a=2=b; // error

Ответ 4

Он устанавливает обе переменные в ноль.

int i, j;
i = j = 0;

То же, что и запись

int i, j;
j = 0;
i = j;

или писать

int i, j;
i = 0;
j = 0;

Ответ 5

Он присваивает ArcBit 0, затем присваивает ArcChar значение выражения ArcBit = 0 (т.е. 0)

Ответ 6

Сама операция присваивания (a = b) возвращает значение r, которое может быть дополнительно присвоено другому lvalue; c = (a = b). В конце, и a, и c будут иметь значение b.

Ответ 7

В некоторых языках присваивания представляют собой утверждения: они вызывают какое-либо действие, но сами не имеют значения. Например, в Python 1 запрещено писать

x = (y = 10) + 5

потому что назначение y = 10 не может использоваться там, где ожидается значение.

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

Использование двух знаков равенства на одной строке интерпретируется следующим образом:

ArcChar = (ArcBit = 0);

То есть: ArcChar запрашивает значение ArcBit = 0, которое равно 0, поэтому обе переменные в конечном итоге составляют 0.


1x = y = 0 на самом деле является законным в Python, но он рассматривает особый случай оператора присваивания, и попытка сделать что-либо более сложное с назначением не удастся.

Ответ 10

Назначение в C является выражением, а не выражением. Также вы можете свободно назначать значения разного размера (без знака char для int и наоборот). Добро пожаловать на язык программирования C:)