demiurg_spb 0 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба Возник тут вопрос. Кусочек программы можно написать двумя способами, но с одним и тем же правильным результатом (компилятор 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба Вопрос: это можно взять на вооружение? Поскольку регистры uart безвариантно являются и прописаны как volatile, то несомнено второй вариант, ибо явные промежуточные переменные просто совсем не нужны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба Спасибо за подсказку. Я, по незнанию, наверное, всегда делал присвоение промежуточной переменной. Что-то подсказывает, что второй вариант тоже законный, но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Не могли бы более знающие товарищи навести на этот пункт (пункты)? С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба Спасибо за подсказку. Всегда рад:) Я, по незнанию, наверное, всегда делал присвоение промежуточной переменной. Что-то подсказывает, что второй вариант тоже законный, но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Не могли бы более знающие товарищи навести на этот пункт (пункты)? С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода. На мой взгляд читаемость лишь улучшается. А вот первоисточник сего финта найти надо, да как вообще это называется очень хочется узнать, чтоб знать хоть что искать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба ...но тщательное чтение стандарта C99 не помогло выявить пункт, который это подтверждает. Кроме прочитать, нужно еще и суть понимать. 1.Упоминание имени переменной означает обращение к ней. Это основы основ. Какие "подтверждения" еще требуются? 2.Для того, что бы "бесполезные" обращения не были выкинуты компилятором есть клбчевое слово volatile. Поиск по доукменту, надеюсь работает? С другой стороны, присваивание промежуточной переменной имеет одно преимущество: даже неискушённые в глубоких тонкостях языка Си поймут, что имелось в виду. На мой взгляд, это сильное преимущество. Не следует жертвовать читаемостью кода. Вcе с точностью до наоборот :( 1. Никаких "тонкостей" нет напрочь - это самые основы. 2. Введение неких ненужных переменных, получение воплей о их ненужности от компилятора, закрытие этих вопплей - да какая уж тут, простите, в результате "читаемость"!? А вот первоисточник сего финта найти надо, "Финты" это как-раз с лишней переменной :( не знаю, какой "умник" такой финт и с какого бодуна применил, но думаю, что его уже не найти :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба 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. Действительно, есть значение выражения, а для его получения необходимо обращение к полю сруктуры. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба Контрпример: взятие адреса переменной. Имя упоминается, а обращения нет. На то это и ДРУГАЯ ОПЕРАЦИЯ. Совсем другая - взятие адреса, а не значения. После... Эко куда Вас понесло..... Зачем? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба 1.Упоминание имени переменной означает обращение к ней. На то это и ДРУГАЯ ОПЕРАЦИЯ. Совсем другая - взятие адреса, а не значения. Я запутался... Взятие адреса - это совсем другая операция по сравнению с упоминанием имени переменной? То есть "var++" - это упоминание имени, а "&var" - нет? Эко куда Вас понесло..... Зачем? Затем, что вопрошающий сказал: "И что стандарт может нам сказать по этому поводу?" Посему стараюсь приводить цитаты из стандарта, имеющие отношение к данному вопросу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 20 октября, 2008 Опубликовано 20 октября, 2008 · Жалоба Я запутался... Взятие адреса - это совсем другая операция по сравнению с упоминанием имени переменной? То есть "var++" - это упоминание имени, а "&var" - нет? Если раскрутить, то получим такую цепочку: var++; var += 1; var = var + 1; Отсюда видно, что что тут происходит не только упоминание переменной всуе:) А взятие адреса - это действие, которое никак не отражается на самой переменной - происходит лишь загрузка в индексный регистр адреса переменной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 21 октября, 2008 Опубликовано 21 октября, 2008 · Жалоба Поскольку регистры uart безвариантно являются и прописаны как volatile, то несомнено второй вариант, ибо явные промежуточные переменные просто совсем не нужны. К примеру MSVS 2008 для ARM в обоих случаях генерит одинаковый код. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 21 октября, 2008 Опубликовано 21 октября, 2008 · Жалоба А взятие адреса - это действие, которое никак не отражается на самой переменной - происходит лишь загрузка в индексный регистр адреса переменной. Есть еще и другие операции, например декларирование, sizeof, ... Посему стараюсь приводить цитаты из стандарта, имеющие отношение к данному вопросу. Ну не обязан стандарт заменять учебник арифметики. Пишем: a = b проговариваем как первоклашки на уроке арифметики - "взяли значение переменной 'b' и присвоили его переменной 'a'" Теперь пишем: b проговариваем - "взяли значение переменной 'b'". И... и все. Все, что нам надо, мы сделали! Ничего лишнего и мутного. Чего не понятно-то? Какие какие такие "тонкости C"? К примеру MSVS 2008 для ARM в обоих случаях генерит одинаковый код. Ну и что? Слава оптимизации! Сначала читатель продирается через нагрможденение ненужностей, потом компилятор. Если оба поняли, что все эти "финты" не нужны совсем, то результаты, етественно будут одинаковые - БЕЗ ФИНТОВ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 21 октября, 2008 Опубликовано 21 октября, 2008 · Жалоба Без финтов - это отлично, но!!! - очень непривычно. Чтение из переменной очевидно, когда оно стоит справа от знака присваивания. И когда этот знак опущен это и вызывает недоумение и неприятие. Я думаю, если бы разместить где-нибудь на форумах вопрос типа: "Что означает выражение для переменной volatile int x?: x;" абсолютное большинство ответит неправильно. Посему, учитывая, что всех не переучишь, и почти все люди работают в коллективах, я бы именно из этих соображений оставил бы: int temp = x;. Коллеге zltigo респект за неординарный подход. Тем более, что почти аналогичное использование чтения переменной, например, в while(x) ни у кого вопросов не вызвало бы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 21 октября, 2008 Опубликовано 21 октября, 2008 · Жалоба Коллеге zltigo респект за неординарный подход. Это единственно верный подход. Или предпочитаете ворнинги давить всем коллективом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 октября, 2008 Опубликовано 21 октября, 2008 · Жалоба Итак, итоги: 1) Согласно стандарту языка для чтения volatile переменной var достаточно написать var; Кому интересно, могу подкрепить это цитатами из стандарта. 2) Очевидно, что такой код не проходит тест "даже моя бабушка поймёт, что это значит". Другими словами, читаемость кода страдает. 3) Вывод. Каждый решает сам, что лучше: - пожетворать читаемостью кода - бороться с предупреждениями компилятора при присваивании вспомогательной переменной dummy = var; Итак, задача сведена к спору "читаемость кода против подавления предупреждений компилятора". Как известно, такой спор заведомо неразрешим, так что дальнейшие дискуссии результата не принесут :-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 21 октября, 2008 Опубликовано 21 октября, 2008 · Жалоба Другими словами, читаемость кода страдает. Это утверждение абсолютно ложное :(, посему и "вывод" такой-же. var; // Это читабельно А что-то типа такого, даже максимально обвешенного для понимания ненужности "финтов": { int tmp = var; tmp = tmp; } // Много, много хуже. А такое: tmp = var; // Вообще безобразие Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться