Является ли плохой практикой arr [0] = arr [1] = значение в C? - PullRequest
3 голосов
/ 04 мая 2020

Как я уже сказал выше, это плохая практика? В ASM как это будет выглядеть? Я имею в виду, я не знаю, переводится ли это как-то так:

arr[0] = value;
arr[1] = value;

или как-то так:

arr[1] = value;
arr[0] = arr[1];

Какой второй вариант явно более неэффективен ( imm vs mem).

Заранее спасибо.

Ответы [ 3 ]

7 голосов
/ 04 мая 2020

В соответствии с C операторы присваивания грамматики оценивают справа налево.

Таким образом, это утверждение

arr[0] = arr[1] = value;

эквивалентно

arr[0] = ( arr[1] = value );

Из C Стандарт (6.5.16 Операторы присваивания)

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

Таким образом, согласно цитате вы можете считать это утверждение

arr[0] = arr[1] = value;

подобным

arr[1] = value;
arr[0] = arr[1];

Что касается эффективности, то компилятор может сгенерировать эффективный объектный код, который будет отличаться от того, что вы представляете, увидев исходный код.

1 голос
/ 05 мая 2020

Ну, я посмотрел код ассемблера и получил следующее:

182             Arr[0] = 0x01;
e357:   A601 LDA #0x01
e359:   C70100 STA 0x0100
184             Arr[0] = Arr[1] = 0x58;
e35d:   A658 LDA #0x58
e35f:   C70101 STA 0x0101
e362:   C70100 STA 0x0100

Так что ожидаемый результат, если я сделаю Arr [0] = 0x58; и сразу Arr [1] = 0x58; is:

e357:   A601 LDA #0x58
e359:   C70100 STA 0x0100
e359:   C70100 STA 0x0101

(STA: STore Accumulator | LDA: LoaD Accumulator)

Итак, используемый мной компилятор оптимизирует код. И вы, люди, говорили, я предполагаю, что лучше практиковать (или лучше читаемый способ), используя:

Arr[0] = 0x58; 
Arr[1] = 0x58;

Спасибо всем!

0 голосов
/ 04 мая 2020

Если вы хотите просмотреть asm, вы можете использовать

objdump -d -M intel binary_name

Затем вы будете искать раздел .text и затем функцию main.


Вот что я получил на своем компьютере, используя int arr[2] и простой printf для использования переменных.

Оптимизированный вывод, скомпилированный с -O3

mov    ecx,0x2a
mov    edx,0x2a

Не оптимизировано

Для этого кода:

arr[0] = 42;
arr[1] = 42;

Вывод:

mov    DWORD PTR [rbp-0x10],0x2a
mov    DWORD PTR [rbp-0xc],0x2a

А для этого кода:

arr[0] = arr[1] = 42;

Вывод :

mov    DWORD PTR [rbp-0xc],0x2a
mov    eax,DWORD PTR [rbp-0xc]
mov    DWORD PTR [rbp-0x10],eax

Во втором случае есть дополнительная операция.

Так что с оптимизированной компиляцией нет никакой разницы, но для читабельности кода я бы не писал так.

...