|
|
  |
Вопрос к знатокам С. |
|
|
|
Oct 20 2008, 16:04
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Возник тут вопрос. Кусочек программы можно написать двумя способами, но с одним и тем же правильным результатом (компилятор 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;
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 20 2008, 17:27
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Спасибо за подсказку. Я, по незнанию, наверное, всегда делал присвоение промежуточной переменной. Что-то подсказывает, что второй вариант тоже законный, но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Не могли бы более знающие товарищи навести на этот пункт (пункты)? С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода.
|
|
|
|
|
Oct 20 2008, 18:05
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(scifi @ Oct 20 2008, 21:27)  Спасибо за подсказку. Всегда рад  Цитата(scifi @ Oct 20 2008, 21:27)  Я, по незнанию, наверное, всегда делал присвоение промежуточной переменной. Что-то подсказывает, что второй вариант тоже законный, но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Не могли бы более знающие товарищи навести на этот пункт (пункты)? С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода. На мой взгляд читаемость лишь улучшается. А вот первоисточник сего финта найти надо, да как вообще это называется очень хочется узнать, чтоб знать хоть что искать.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 20 2008, 18:17
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(scifi @ Oct 20 2008, 19:27)  ...но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Кроме прочитать, нужно еще и суть понимать. 1.Упоминание имени переменной означает обращение к ней. Это основы основ. Какие "подтверждения" еще требуются? 2.Для того, что бы "бесполезные" обращения не были выкинуты компилятором есть клбчевое слово volatile. Поиск по доукменту, надеюсь работает? Цитата С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода. Вcе с точностью до наоборот 1. Никаких "тонкостей" нет напрочь - это самые основы. 2. Введение неких ненужных переменных, получение воплей о их ненужности от компилятора, закрытие этих вопплей - да какая уж тут, простите, в результате "читаемость"!? Цитата А вот первоисточник сего финта найти надо, "Финты" это как-раз с лишней переменной  не знаю, какой "умник" такой финт и с какого бодуна применил, но думаю, что его уже не найти
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 20 2008, 18:35
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(zltigo @ Oct 20 2008, 22:17)  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. Действительно, есть значение выражения, а для его получения необходимо обращение к полю сруктуры.
|
|
|
|
|
Oct 20 2008, 19:11
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(scifi @ Oct 20 2008, 20:35)  Контрпример: взятие адреса переменной. Имя упоминается, а обращения нет. На то это и ДРУГАЯ ОПЕРАЦИЯ. Совсем другая - взятие адреса, а не значения. Цитата После... Эко куда Вас понесло..... Зачем?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 20 2008, 19:34
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(zltigo @ Oct 20 2008, 22:17)  1.Упоминание имени переменной означает обращение к ней. Цитата(zltigo @ Oct 20 2008, 23:11)  На то это и ДРУГАЯ ОПЕРАЦИЯ. Совсем другая - взятие адреса, а не значения. Я запутался... Взятие адреса - это совсем другая операция по сравнению с упоминанием имени переменной? То есть "var++" - это упоминание имени, а "&var" - нет? Цитата(zltigo @ Oct 20 2008, 23:11)  Эко куда Вас понесло..... Зачем? Затем, что вопрошающий сказал: "И что стандарт может нам сказать по этому поводу?" Посему стараюсь приводить цитаты из стандарта, имеющие отношение к данному вопросу.
|
|
|
|
|
Oct 20 2008, 19:53
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(scifi @ Oct 20 2008, 23:34)  Я запутался... Взятие адреса - это совсем другая операция по сравнению с упоминанием имени переменной? То есть "var++" - это упоминание имени, а "&var" - нет? Если раскрутить, то получим такую цепочку: var++; var += 1; var = var + 1; Отсюда видно, что что тут происходит не только упоминание переменной всуе  А взятие адреса - это действие, которое никак не отражается на самой переменной - происходит лишь загрузка в индексный регистр адреса переменной.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 21 2008, 15:57
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(demiurg_spb @ Oct 20 2008, 21:53)  А взятие адреса - это действие, которое никак не отражается на самой переменной - происходит лишь загрузка в индексный регистр адреса переменной. Есть еще и другие операции, например декларирование, sizeof, ... Цитата Посему стараюсь приводить цитаты из стандарта, имеющие отношение к данному вопросу. Ну не обязан стандарт заменять учебник арифметики. Пишем: a = b проговариваем как первоклашки на уроке арифметики - "взяли значение переменной 'b' и присвоили его переменной 'a'" Теперь пишем: b проговариваем - "взяли значение переменной 'b'". И... и все. Все, что нам надо, мы сделали! Ничего лишнего и мутного. Чего не понятно-то? Какие какие такие "тонкости C"? Цитата(sergeeff @ Oct 21 2008, 17:08)  К примеру MSVS 2008 для ARM в обоих случаях генерит одинаковый код. Ну и что? Слава оптимизации! Сначала читатель продирается через нагрможденение ненужностей, потом компилятор. Если оба поняли, что все эти "финты" не нужны совсем, то результаты, етественно будут одинаковые - БЕЗ ФИНТОВ.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 21 2008, 17:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Без финтов - это отлично, но!!! - очень непривычно. Чтение из переменной очевидно, когда оно стоит справа от знака присваивания. И когда этот знак опущен это и вызывает недоумение и неприятие.
Я думаю, если бы разместить где-нибудь на форумах вопрос типа: "Что означает выражение для переменной volatile int x?: x;"
абсолютное большинство ответит неправильно. Посему, учитывая, что всех не переучишь, и почти все люди работают в коллективах, я бы именно из этих соображений оставил бы: int temp = x;.
Коллеге zltigo респект за неординарный подход. Тем более, что почти аналогичное использование чтения переменной, например, в while(x) ни у кого вопросов не вызвало бы.
|
|
|
|
|
Oct 21 2008, 17:42
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Итак, итоги: 1) Согласно стандарту языка для чтения volatile переменной var достаточно написать Код var; Кому интересно, могу подкрепить это цитатами из стандарта. 2) Очевидно, что такой код не проходит тест "даже моя бабушка поймёт, что это значит". Другими словами, читаемость кода страдает. 3) Вывод. Каждый решает сам, что лучше: - пожетворать читаемостью кода - бороться с предупреждениями компилятора при присваивании вспомогательной переменной Код dummy = var; Итак, задача сведена к спору "читаемость кода против подавления предупреждений компилятора". Как известно, такой спор заведомо неразрешим, так что дальнейшие дискуссии результата не принесут :-)
|
|
|
|
|
Oct 21 2008, 17:52
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(scifi @ Oct 21 2008, 19:42)  Другими словами, читаемость кода страдает. Это утверждение абсолютно ложное  , посему и "вывод" такой-же. Код var; // Это читабельно А что-то типа такого, даже максимально обвешенного для понимания ненужности "финтов": Код { int tmp = var; tmp = tmp; } // Много, много хуже. А такое: Код tmp = var; // Вообще безобразие
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|