Комментарии 57
А вы в хромиум багрепорты\патчи отправили? :)
-8
Автор молодец! Буду теперь разбирать статью.
0
В лиспе таких ошибок не сделать.
0
В лиспе можно работать с opencv? Там есть какие-нибудь библиотеки для обработки изображений и распознавания образов?
0
github.com/ryepup/cl-opencv — но мне ее нашел гугл, сам не использовал.
Для обработки изображений есть, например, github.com/slyrus/opticl
Для обработки изображений есть, например, github.com/slyrus/opticl
+2
Только думал стоит ли чаще использовать скобки в "?:", т.к. зачастую их игнорируют и пишут выражения как можно сжато. И вот очевидные плюсы скобок!
+2
Хорошая статья!
0
Я зашел на сайт Newton Dynamics чтобы найти игру с танком на картинке, но в Showcase нету ничего про танки
Где вы ее взяли?
Где вы ее взяли?
0
0
Это демонстрация работы движка. Ролики можно посмотреть здесь.
0
Скобки вообще редко вредят читабельности кода. Нас учили при малейшем сомнении в приоритетах операторов ставить скобки :)
У Страуструпа в самом начале сказано, что С++ одновременно и любят и ненавидят за возможность конструкций типа --*p++.
У Страуструпа в самом начале сказано, что С++ одновременно и любят и ненавидят за возможность конструкций типа --*p++.
+11
Любопытно, что в Java из-за более строгой системы типов такой проблемы не возникает:
Интересно, распознавание таких вещей в плюсах на уровне компилятора (выдача варнинга) ничему не противоречит? GCC -Wall -Wextra молчит на такую строчку.
Интересно, распознавание таких вещей в плюсах на уровне компилятора (выдача варнинга) ничему не противоречит? GCC -Wall -Wextra молчит на такую строчку.
+8
А на что здесь ругаться компилятору? Вполне законная конструкция. Это удел статических анализаторов, которые занимаются некой эвристикой.
0
Неиспользуемая переменная тоже вполне законна, но компилятор выдаёт варнинг :-)
+2
Что такое неиспользуемая переменная это просто и понятно. Диагностика ошибки с "?:" не столь очевидна и компиляторы не затачивают на подобную сложную логику анализа. Вот описание диагностики V502. Это я просто скопировал комментарий из кода PVS-Studio:
/*
Общее правило N2.
Генерирует предупреждение V502.
(Сам придумал (Андрей Карпов). Аналогов не видел.)
Выражение с оператором '?:' считается опасным, если слева от него последняя переменная имеет
тип bool или BOOL и при этом слева от нее есть оператор с приоритетом выше чем у '?:'.
А именно опасным считаем: ||, &&, |, ......, /, *.
Пример:
int a;
bool b;
int c = a + b ? 0 : 1;
Исключения:
1) Еще левее объект также имеет тип bool или BOOL.
2) Оператором слева является || или &&, и при этом левее расположен объект является
указателем или указатель это то, что возвращает оператор ?:.
Это кажется странным, но подобные конструкции действительно неопасны, так как
невозможно компилировать:
"int = ptr && (bool ? int : int)"
"ptr = ptr && (bool ? ptr : ptr)"
"bool = (int && bool) ? ptr : ptr"
Пример кода для исключения:
Tobj *p;
x = p && a==b ? p->foo() : 0;
*/
+4
Спасибо за детальное объяснение правила. Интересно, у вас все комментарии на русском? :-)
0
На то, что boolean и int — разные вещи (в зависимости от языка).
В плюсах можно очень легко на грабли наступить из-за того, что в качестве boolean может выступать что угодно. Например, недавно наткнулся на такой код:
Вроде бы всё хорошо, вот только в данном случае это должна была быть функция
В плюсах можно очень легко на грабли наступить из-за того, что в качестве boolean может выступать что угодно. Например, недавно наткнулся на такой код:
if (obj.is_null) { ... }
Вроде бы всё хорошо, вот только в данном случае это должна была быть функция
is_null()
, и указатель на функцию автоматом привёлся к boolean0
Если в лоб предупреждать, что в выражении тип bool смешивается с типом int, большинство программистов это выключат. Слишком много подобного кода. По крайней мере я очень много видел. Что стоят только проверки вида:
bool x;
if (x & 1 > 0)
Да, так пишут. Вот только что рассматривал подобный образец искусства. Это работает и никто не кинется перелопачивать мегабайты кода в целях эстетической красоты. :)
Нужны более сложные проверки. Описание подобной, я привел выше. В компиляторах по возможности стараются реализовывать более очевидные.
bool x;
if (x & 1 > 0)
Да, так пишут. Вот только что рассматривал подобный образец искусства. Это работает и никто не кинется перелопачивать мегабайты кода в целях эстетической красоты. :)
Нужны более сложные проверки. Описание подобной, я привел выше. В компиляторах по возможности стараются реализовывать более очевидные.
0
Если в Java написать нечто подобное:
то компилятор это съест, однако же подобная ошибка останется.
bool Z = X && (A == B) ? !A : !B;
то компилятор это съест, однако же подобная ошибка останется.
+1
Верно. Но, согласитесь, пример довольно искусственный :-) Если A равно B, то обе ветки тернарного оператора тоже равны, поэтому выражение сводится к
Можно, наверно, выдумать что-то более приближенное к реальности, но в своей практике я не припомню примеров, чтобы тернарный оператор требовался в чисто булевом выражении.
bool Z = X && !B;
Можно, наверно, выдумать что-то более приближенное к реальности, но в своей практике я не припомню примеров, чтобы тернарный оператор требовался в чисто булевом выражении.
0
Кроме того, PVS-Studio на этот пример также промолчит :-)
0
Хорошая статья. На сколько же граблей наступил, пока не дошёл до того-же самого.
0
А зачем реклама в тексте поста? (это не хабрахабровская)
-9
иногда удобно
#define cond(p,t,f) ((p)?(t):(f))
0
Макросы плохи по множеству причин. Уж лучше тогда inline функцию сделать.
+3
Например? (Нет, не буду утверждать, что макросы всем хороши, но интересен этот момент.) Чем плох этот макрос? Чем лучше аналогичный inline?
0
Конкретно этот — кажется ничем. А вообще почти всегда макрос, это усложнение отладки и т.д.
0
И многие другие тоже ничем. Поэтому я и не гнушаюсь пользоваться макросами. Умелое их применение позволяет сильно улучшить читабельность и гибкость кода. То же самое относится и к другим видам препроцессинга. У меня зачастую применяется ещё m4 и некоторые кастомные вещи.
Насчёт усложнения отладки — только при ошибках в макросах. Директива
Насчёт усложнения отладки — только при ошибках в макросах. Директива
#line
неспроста придумана.0
Вот интересно, как различные системы code-assist с макросами дружат? Даже конкретно на этом примере. Определят ли они возвращаемый тип этого макроса, чтобы на этапе написания кода отследить несоответствие типов (скажем, результат cond() подаётся параметром в функцию)? Проверят ли, что тип второго и третьего аргумента должен совпадать? Выдадут ли всплывающую подсказку по типам аргументов cond()? Всё-таки в плане контроля типов шаблонированная inline-функция кажется надёжнее.
+1
Контроль типов произведёт компилятор, если про него забудет программист. А если какая-то система «code assist» не умеет стандартный препроцессор — это плохая система.
И потом, какие шаблоны в C?
И потом, какие шаблоны в C?
0
Пост вроде в блоге C++, в ветке комментариев C не упоминался, так что вопрос скорее «а при чём тут C?» :-) Сомневаюсь, что даже продвинутый code assist подскажет, что первым параметром cond должен идти булев аргумент, потому что явно в макросе это нигде не сказано (а в inline-функции будет сказано). Пусть знатоки плюсовых IDE подскажут. Контроль типов на этапе написания кода существенно ускоряет работу и освобождает голову для более важных вещей. У меня, к примеру, благодаря code assist, ошибки компиляции практически никогда не встречаются, экономя мне время на лишние запуски компиляции.
+2
По поводу этого макроса, могу сказать, что скорее всего человеку, который будет читать этот код, придется смотреть определение этого макроса.
0
Практически всегда и везде беру все что можно в скобки.
Приоритеты операций знать конечно нужно, но не дай бог из-за глупой ошибки полезут рандомные трудноотлаживаемые баги… Лучше написать немного лишних скобок и получить гарантию, что операции будут выполняться в верном порядке.
Приоритеты операций знать конечно нужно, но не дай бог из-за глупой ошибки полезут рандомные трудноотлаживаемые баги… Лучше написать немного лишних скобок и получить гарантию, что операции будут выполняться в верном порядке.
+1
А на каком основании анализатор выдает такое уверенное сообщение о том, что тернарный оператор используется не правильно? Возможно разработчик имел ввиду именно то, что написал.
0
Кстати, я подумал о том же, когда посмотрел на код Newton Game Dynamics к примеру.
0
На Newton Game Dynamics видно, что ошибка, потому что на bool умножение, а вот в хромиуме не понятно. Наверно стоило бы добавить слово «возможно» в текст сообщения.
0
Yep, my fault :D
0
Ну вот другой примерчик. ;) Не Chromium, но его составная часть (библиотека Sanitiser for OpenType). Здесь вообще условие всегда истинное получается:
// Copyright © 2011 The Chromium Authors.
// ...
bool version_2;
bool ots_gdef_parse(...)
{
...
const unsigned gdef_header_end = static_cast(8) +
gdef->version_2 ? static_cast(2) : static_cast(0);
...
}
+1
Вы не поверите :) но сообщение анализатора начинается со слова «Возможно»:
Perhaps the '?:' operator works in a different way than it was expected.
Perhaps the '?:' operator works in a different way than it was expected.
+2
Иногда он конечно и ошибается. Но очень подозрительно, например, что здесь bool умножается на float.
Очень сомневаюсь, что так и задумано. :)
С другими примерами аналогичная ситуация.
den = dgFloat32 (1.0e-24f) *
(den > dgFloat32 (0.0f)) ? dgFloat32 (1.0f) : dgFloat32 (-1.0f);
Очень сомневаюсь, что так и задумано. :)
С другими примерами аналогичная ситуация.
0
это лишь малая часть С++ айсберга
а в целом начало отличное.
Спасибо
а в целом начало отличное.
Спасибо
+1
Ха! Именно сегодня мне понадобилось создавать ссылки внутри функции (ранее использовал их лишь в качестве жёстких алиасов), и порадовался при этом тому, как оператор ?: классно подходит для их инициализации! :)
0
не смотря на то, что вы пиарите свою студию, статьи у вас интересные и почитать любо-дорого) спасибо
+2
Что-то вас тут подвел хостинг картинок — грузятся совсем левые вещи…
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Как уменьшить вероятность ошибки на этапе написания кода. Заметка N2