путаница операции присваивания - PullRequest
3 голосов
/ 21 марта 2011

Что выводит следующий код:

int main() {
  int k = (k = 2) + (k = 3) + (k = 5);
  printf("%d", k);
}

Это не дает никакой ошибки, почему?Я думаю, что это должно дать ошибку, потому что операции присваивания находятся в той же строке, что и определение k.

Я имею в виду, что int i = i; не может компилироваться.Но это компилируется.Зачем?Какой будет выход и почему?

Ответы [ 3 ]

7 голосов
/ 21 марта 2011

int i = i компилируется, потому что 3.3.1 / 1 (C ++ 03) говорит:

Точка объявления имени находится сразу после его полного декларатора и до его инициализатора

То есть i инициализируется с его собственным неопределенным значением.

Однако код вызывает неопределенное поведение, поскольку k изменяется более одного раза между двумя точками последовательности.Прочтите этот FAQ по Неопределенные точки поведения и последовательности

0 голосов
/ 21 марта 2011

Ух ты, я тоже получил 11. Я думаю, что k получает 3, а затем один раз 5 для добавления. Если сделать только int k = (k=2)+(k=3), то получится 6, а int k = (k=2)+(k=4) - 8, а int k = (k=2)+(k=4)+(k=5) - 13. int k = (k=2)+(k=4)+(k=5)+(k=6) даст 19 (4 + 4 + 5 + 6).

Моя догадка? Дополнение делается слева направо. Первые два (k = x) выражения добавляются, и результат сохраняется в регистре или в стеке. Однако, поскольку это k + k для этого выражения, оба добавляемых значения равны тому, что в данный момент является k, что является вторым выражением, потому что оно вычисляется после другого (переопределяя его присваивание k). Однако после этого начального добавления результат сохраняется в другом месте, поэтому теперь он защищен от подделки (изменение k не повлияет на него). Двигаясь слева направо, каждое последующее добавление переназначает k (не влияет на текущую сумму) и добавляет k к текущей сумме.

0 голосов
/ 21 марта 2011

int i = i;сначала определяет переменную, а затем присваивает ей значение.В C вы можете читать из неинициализированной переменной.Это никогда не является хорошей идеей, и некоторые компиляторы выдают предупреждающее сообщение, но это возможно.

И в C назначения также являются выражениями.Вывод будет «10», или это было бы, если бы у вас было «k» вместо «a».

...