Перейти к содержанию
    

Вопрос к знатокам С.

Возник тут вопрос.

Кусочек программы можно написать двумя способами,

но с одним и тем же правильным результатом (компилятор avr-gcc 4.1.2).

Вопрос: это можно взять на вооружение?

И что стандарт может нам сказать по этому поводу?

Спасибо.

//============================================
    unsigned char temp;

    temp = *uart->pUDR;   // Очищаем буфер 3-его уровня.
    temp = *uart->pUDR;   
    temp = *uart->pUDR;   

//============================================
    *uart->pUDR;   // Очищаем буфер 3-его уровня.
    *uart->pUDR;   
    *uart->pUDR;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос: это можно взять на вооружение?

Поскольку регистры uart безвариантно являются и прописаны как volatile, то несомнено второй вариант, ибо явные промежуточные переменные просто совсем не нужны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за подсказку.

Я, по незнанию, наверное, всегда делал присвоение промежуточной переменной. Что-то подсказывает, что второй вариант тоже законный, но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Не могли бы более знающие товарищи навести на этот пункт (пункты)?

С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за подсказку.

Всегда рад:)

Я, по незнанию, наверное, всегда делал присвоение промежуточной переменной. Что-то подсказывает, что второй вариант тоже законный, но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Не могли бы более знающие товарищи навести на этот пункт (пункты)?

С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода.

На мой взгляд читаемость лишь улучшается.

А вот первоисточник сего финта найти надо, да как вообще это называется очень хочется узнать, чтоб знать хоть что искать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает.

Кроме прочитать, нужно еще и суть понимать.

1.Упоминание имени переменной означает обращение к ней. Это основы основ. Какие "подтверждения" еще требуются?

2.Для того, что бы "бесполезные" обращения не были выкинуты компилятором есть клбчевое слово volatile. Поиск по доукменту, надеюсь работает?

С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода.

Вcе с точностью до наоборот :(

1. Никаких "тонкостей" нет напрочь - это самые основы.

2. Введение неких ненужных переменных, получение воплей о их ненужности от компилятора, закрытие этих вопплей - да какая уж тут, простите, в результате "читаемость"!?

А вот первоисточник сего финта найти надо,

"Финты" это как-раз с лишней переменной :( не знаю, какой "умник" такой финт и с какого бодуна применил, но думаю, что его уже не найти :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1.Упоминание имени переменной означает обращение к ней. Это основы основ. Какие "подтверждения" еще требуются?

Контрпример: взятие адреса переменной. Имя упоминается, а обращения нет.

 

После дополнительного прочтения стандарта начинает вырисовываться:

- The expression in an expression statement is evaluated as a void expression for its side effects.

- A postfix expression followed by the -> operator and an identifier designates a member of a structure or union object. The value is that of the named member of the object to which the first expression points, and is an lvalue.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Контрпример: взятие адреса переменной. Имя упоминается, а обращения нет.

На то это и ДРУГАЯ ОПЕРАЦИЯ. Совсем другая - взятие адреса, а не значения.

После...

Эко куда Вас понесло..... Зачем?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1.Упоминание имени переменной означает обращение к ней.

На то это и ДРУГАЯ ОПЕРАЦИЯ. Совсем другая - взятие адреса, а не значения.

Я запутался... Взятие адреса - это совсем другая операция по сравнению с упоминанием имени переменной? То есть "var++" - это упоминание имени, а "&var" - нет?

 

Эко куда Вас понесло..... Зачем?

Затем, что вопрошающий сказал: "И что стандарт может нам сказать по этому поводу?" Посему стараюсь приводить цитаты из стандарта, имеющие отношение к данному вопросу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я запутался... Взятие адреса - это совсем другая операция по сравнению с упоминанием имени переменной? То есть "var++" - это упоминание имени, а "&var" - нет?

Если раскрутить, то получим такую цепочку:

var++;

var += 1;

var = var + 1;

 

Отсюда видно, что что тут происходит не только упоминание переменной всуе:)

А взятие адреса - это действие, которое никак не отражается на самой переменной -

происходит лишь загрузка в индексный регистр адреса переменной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поскольку регистры uart безвариантно являются и прописаны как volatile, то несомнено второй вариант, ибо явные промежуточные переменные просто совсем не нужны.

 

 

К примеру MSVS 2008 для ARM в обоих случаях генерит одинаковый код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А взятие адреса - это действие, которое никак не отражается на самой переменной -

происходит лишь загрузка в индексный регистр адреса переменной.

Есть еще и другие операции, например декларирование, sizeof, ...

Посему стараюсь приводить цитаты из стандарта, имеющие отношение к данному вопросу.

Ну не обязан стандарт заменять учебник арифметики.

Пишем:

a = b

проговариваем как первоклашки на уроке арифметики - "взяли значение переменной 'b' и присвоили его переменной 'a'"

Теперь пишем:

b

проговариваем - "взяли значение переменной 'b'". И... и все. Все, что нам надо, мы сделали! Ничего лишнего и мутного. Чего не понятно-то? Какие какие такие "тонкости C"?

 

 

К примеру MSVS 2008 для ARM в обоих случаях генерит одинаковый код.

Ну и что? Слава оптимизации! Сначала читатель продирается через нагрможденение ненужностей, потом компилятор. Если оба поняли, что все эти "финты" не нужны совсем, то результаты, етественно будут одинаковые - БЕЗ ФИНТОВ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Без финтов - это отлично, но!!! - очень непривычно. Чтение из переменной очевидно, когда оно стоит справа от знака присваивания. И когда этот знак опущен это и вызывает недоумение и неприятие.

 

Я думаю, если бы разместить где-нибудь на форумах вопрос типа: "Что означает выражение для переменной volatile int x?: x;"

 

абсолютное большинство ответит неправильно. Посему, учитывая, что всех не переучишь, и почти все люди работают в коллективах, я бы именно из этих соображений оставил бы: int temp = x;.

 

Коллеге zltigo респект за неординарный подход. Тем более, что почти аналогичное использование чтения переменной, например, в while(x) ни у кого вопросов не вызвало бы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Коллеге zltigo респект за неординарный подход.

Это единственно верный подход. Или предпочитаете ворнинги давить всем коллективом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Итак, итоги:

1) Согласно стандарту языка для чтения volatile переменной var достаточно написать

var;

Кому интересно, могу подкрепить это цитатами из стандарта.

2) Очевидно, что такой код не проходит тест "даже моя бабушка поймёт, что это значит". Другими словами, читаемость кода страдает.

3) Вывод. Каждый решает сам, что лучше:

- пожетворать читаемостью кода

- бороться с предупреждениями компилятора при присваивании вспомогательной переменной

dummy = var;

 

Итак, задача сведена к спору "читаемость кода против подавления предупреждений компилятора". Как известно, такой спор заведомо неразрешим, так что дальнейшие дискуссии результата не принесут :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Другими словами, читаемость кода страдает.

Это утверждение абсолютно ложное :(, посему и "вывод" такой-же.

var; // Это читабельно

А что-то типа такого, даже максимально обвешенного для понимания ненужности "финтов":

{
int tmp = var;
tmp = tmp;
}  // Много, много хуже.

А такое:

tmp = var; // Вообще безобразие

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...