Начало » Общение на свободные темы » Общение на свободные темы » Заметки программиста С++
Заметки программиста С++ [сообщение #443] |
Чтв, 24 Май 2007 13:32 |
Денис Шевченко
Сообщений: 53 Зарегистрирован: Март 2005 Географическое положение: Москва
|
Member |
|
|
Приветствую всех!
Уж не знаю, сколь много среди участников форума программистов на С и/или С++, но, надеюсь, не я один. Поэтому хочу поделиться маленькими хитростями, полезными в создании программных продуктов.
Все нижесказанное воспринимать как мое личное мнение, однако подискутировать готов.
|
|
|
|
Re: Заметки программиста С++ [сообщение #445 является ответом на сообщение #443] |
Чтв, 24 Май 2007 13:51 |
Денис Шевченко
Сообщений: 53 Зарегистрирован: Март 2005 Географическое положение: Москва
|
Member |
|
|
Нашли? Ну ладно, вот подсказка: что происходит с флагом b? Проверка? Нет, присваивание! Знак проверки на равенство "==" случайно (а может, и не случайно ) перепутан со знаком присваивания "="! В результате нечто ОЧЕНЬ важное, что должно было произойти, не произойдет.
Как решить эту проблему? Вы скажете, что нужно быть внимательными. Да, это так. Но программисты НЕ всегда внимательны, в силу разных причин.
Есть другой путь, который ГАРАНТИРОВАННО избавляет от продемонстрированной ошибки в БОЛЬШИНСТВЕ случаев! Я сам пользуюсь этим приемом, и вам очень советую!
Вспомним теорию языка. В выражении а = 2 а является lvalue, а 2 - rvalue. Ошибка в приведенном мною примере тем опасна, что компилятор ее не покажет, поскольку синтаксис языка нарушен не был. Я сам накалывался на подобную ошибку и тратил немало времени на ее обнаружение. Способ избежать такой ошибки в БОЛЬШИНСТВЕ случаев прост: поменяйте местами lvalue и rvalue! Тогда получится не a = 2, а 2 = a. Но постойте! Это же ошибка! Константа не может быть lvalue! Мы ведь не можем присвоить что-либо числу 2. Любой компилятор, старый или новый, поддерживающий стандарт С++ или неподдерживающий, сразу покажет эту ошибку.
Значит, если нужно, как в приведенном мною примере, проверить условие b == 2, то если мы напишем 2 == b, то ничего не измениться, проверка условия произойдет по-любому. А вот если теперь я перепутаю (или захочу навредить ) и напишу 2 = b, то присваивания уже НЕ произойдет, компилятор выдаст сообщение об ошибке.
Вот и решение проблемы. Однако я сказал выше, что это работает в БОЛЬШИНСТВЕ случаев, то есть не всегда. Да, это не работает в том лишь случае, если обе проверяемые на равенство переменные являются lvalue, однако это встречается значительно реже. В этом случае нужно быть ПРОСТО внимательным.
[Обновления: Чтв, 24 Май 2007 14:15] Известить модератора
|
|
|
Re: Заметки программиста С++ [сообщение #491 является ответом на сообщение #443] |
Вск, 10 Июнь 2007 23:54 |
Денис Шевченко
Сообщений: 53 Зарегистрирован: Март 2005 Географическое положение: Москва
|
Member |
|
|
Всем привет!
Еще одним советом поспешу поделиться.
Есть следующий код:
...
int main()
{
...
for (int i = 0; i < 10; i++) {
// Что-то делаю с участием переменной i
}
...
}
Как известно, в языке С++ можно определять переменную прямо в цикле for. В приведенном примере это переменная i. Вопрос в следующем: какова область видимости внутренней переменной i? Многие (и я, до не давнего времени) сказали бы: "Ну, это просто: область видимости i расположена внутри скобок цикла for. То есть за пределами цикла внутренняя переменная исчезает". И они были бы совершенно правы, но лишь в том случае, если подразумевается использование современных компиляторов, поддерживающих стандарт языка. А если компилятор старый? Я, например, вынужден пользоваться на работе именно таким. Так вот, в старых компиляторах область видимости внутренней переменной i совпадает с областью видимости самого цикла for! То есть, в вышеприведенном примере, i будет существовать до конца функции main()! А это плохо, так как мы не подразумевали, что i окажется где-либо вне цикла. Что будет, если мы напишем так:
...
int main()
{
...
for (int i = 0; i < 10; i++) {
// Что-то делаю с участием переменной i
}
...
int i; // новая переменная, нужная для каких-то других целей
...
}
Но так нельзя! Будет нарушено правило одного определения, так как i, определенная внутри цикла for, будет конфликтовать с новой i.
Есть очень простое решение указанной проблемы, одинаково действенное для любого компилятора: заключите цикл в дополнительные скобки!
...
int main()
{
...
{ for (int i = 0; i < 10; i++) {
// Что-то делаю с участием переменной i
} }
...
int i; // теперь i из цикла не имеет к
// этой i никакого отношения
}
Создав дополнительными фигурными скобками маленькую область видимости, мы гарантировали себя от ошибок, рассмотренных выше.
[Обновления: Вск, 10 Июнь 2007 23:58] Известить модератора
|
|
|
Re: Заметки программиста С++ [сообщение #493 является ответом на сообщение #443] |
Пнд, 11 Июнь 2007 23:20 |
Денис Шевченко
Сообщений: 53 Зарегистрирован: Март 2005 Географическое положение: Москва
|
Member |
|
|
Еще один прикол - триграфы в строчных комментариях.
Есть следующий код:
...
int main()
{
...
if ( i < 3 ) {
i = 3; //????????????/
int b = 10; // А это очень важное действие!
}
}
Так вот, очень важное действие с переменной b НЕ произойдет! Почему, спросите вы? Обратите внимание на три последних знака в первом комментарии, в котором нам почему-то понадобилось указать много знаков вопроса: "??/" Эти три знака образуют триграф, который преобразуется к знаку "\", соединяющий строки (конкатенация)! Таким образом, комментарий с вопросительными знаками будет объединен со строкой, в которой должно произойти очень важное действие. И важная строка будет также закомментированной. Я проверял, это действительно так!
Причем ваш редактор, скорее всего, показывающий закомментированный текст определенным цветом, в данной ситуации НЕ покажет строку с очень важным действием как закомментаренную. И компилятор не ругнется. Впрочем, это относится не ко всем компиляторам, но g++ точно не ругнется, ибо он не просматривает содержимое комментариев, считая это бесполезным. Но в приведенном мною примере такой подход приведет к ошибке.
Совет один: не допускайте триграфов в комментариях.
[Обновления: Пнд, 11 Июнь 2007 23:26] Известить модератора
|
|
|
|
|
Переход к форуму:
|