Одна компания выпускающая статически анализатор сделала конкурс. И для этого конкурса их анализатор можно использовать бесплатно =). Ну я не мог пройти мимо..
У меня пару вопросов появилось..
На сколько правильно uint инициализировать значением -1?
методом научного тыка я выяснил что в gcc
std::numeric_limits<uint>::max() == uint(-1)
Вопрос должен звучать так: а для чего мне понадобилось пихать число со знаком в переменную ,беззнакового целочисленного типа?
Я решил с помощью pvs проверить пару больших и часто подающих программ =) ....
Дак вот.. В одном из проекте так инициализируются переменные класса
class A{
uint a;
uint b;
...
public:
A():a(-1), b(-1)..{}
}
Вот у меня и появился вопрос.. Насколько это нормальный и кроссплатформенный способ получить std::numeric_limits::max() или все таки это ошибка.
Хотя может я предположил что автор хотел получить максимальное число.. А на самом деле после рефакторинга int превратился в uint, а конструктор остался прежним.. Тогда это 100% ошибка.
При присваивании значения одного типа в переменную другого типа, необходимо явное преобразование типов. Правда сказать я не знаю как это делается в плюсах. Так что подумайте, нормальный это способ или не нормальный.
Как использовать PVS-Studio бесплатно ( легальный способ )
Я проверял kdevelop, akregator, plasma и kwin. Вносить в каждый файл комментарии не хотелось =) Да и я этим занялся ради интереса .
Лвиная доля уведомления это не все переменные класса инициализированы и не проверяется на ноль результат работы dynamic_cast=).
Нашел правда и пару ошибок. =)
/kde/workspace/plasma-workspace/libtaskmanager/launchertasksmodel.cpp
KService::Ptr service;
***
if (!service && !service->isApplication()) {
return;
}
Я как понял мы убеждаемся что service имеет нулевой указатель и потом его разыменовываем =)
kde/workspace/plasma-desktop/kcms/phonon/audiosetup.cpp
switch (state) {
case PA_CONTEXT_UNCONNECTED: name = QLatin1Literal("Unconnected");
case PA_CONTEXT_CONNECTING: name = QLatin1Literal("Connecting");
case PA_CONTEXT_AUTHORIZING: name = QLatin1Literal("Authorizing");
****
}
Похоже что тут нужен брейк. И еще пару таких мест есть.
kde/pim/akregator/interfaces/feedstorage.h
bool operator<(const Category &other) const
{
return other.scheme < other.scheme || (other.scheme == other.scheme && term < other.term);
}
Выглядит странно сравнивать одно и тоже other.scheme < other.scheme
И там еще куча странных условия. Забытых операторов delete пару есть. =) И это я только пару программ проверил..
Там есть раздел "автоматизация". Утилита, которая автоматом добавляет нужные изменения.
Допустим, у вас проект под гитом (очень странно, если нет). Вносите изменения с помощью утилиты (одна команда), проверяете, делаете дискард =)
У KDE и связанных проектов есть своя система закидывания патчей:
https://git.reviewboard.kde.org
Она несколько более древняя и кривая чем тот же github, но вполне рабочая.
Вот туда и следует закинуть для обсуждения все подобные места, чтобы работа не пропала даром.
С++ приведение типов проходит неявно=) Не уверен что это по стандарту.
Вполне нормально компилирует clang
char num1 = 10000;
char num2 = std::numeric_limits<unsigned long>::max();
unsigned int num3 = -10;
Хотя и компилятор бросает предупреждение, но не ошибку.
В С++ явное приведение тип также как и в С =)
char num1 = (char) 10000;
можно еще
char num1 = char (10000);
char num1 = static_cast<char>(10000);
По теме: это говнокодный подход. Написание конструкций, смысл которых не очевиден, пусть они даже совершенно правильно используют нюансы работы компиляторов - это говнокод.
А вообще по темам программирования, правильно, грамотно может объяснить MacLeod, так как он профи. А я всего лишь криворукий, бестолковый, любитель. Который умеет инициализировать переменные, проводить простейшие арифметические операции а результат операции выводить на экран. Это все что я знаю и умею :)
Это "наследие С", в котором все скалярные типы неявно приводятся между собой.
Например
int foo() {
double a = 'q';
return a;
}
Вполне валидный код.
Другое дело, что такое сейчас не поощряется, т.к., как правильно писал MacLeod, смысл кода становится не вполне очевиден.
Насколько мне не изменяет склероз - uint переводится как беззнаковая (unsigned) целочисленная переменная.
По теме: это говнокодный подход. Написание конструкций, смысл которых не очевиден, пусть они даже совершенно правильно используют нюансы работы компиляторов - это говнокод.
Всегда очень велика вероятность, что с кодовой базой будут работать (улучшать, дополнять). Написание говнокода сильно усложняет этот процесс. Код должен нормально читаться другим программистом, а не угадываться.
Если такая проблема использовать константу из сторонней библиотеки - вводи свою.
Нужно было глянуть реализацию std::string =). Оказалось что этот метод получения максимального значения используется и в стандартной библиотеке С++.
/// Value returned by various member functions when they fail.
static const size_type npos = static_cast<size_type>(-1);
size_type это unsigned long
стандарт C++ не говорит четко, как представляются отрицательные целые и, соответственно, что будет значением unsigned(-1). возможно в стандарте C что-то есть.
Но всё дело в том, что последние разработки процессоров опираются на использование дополнительного кода для отрицательных, с которым можно складывать и вычитать signed и unsigned одними и теми же инструкциями проца.
поэтому почти не задумываясь можно лепить короткую запись unsigned(-1) вместо длинной
std::numeric_limits<unsigned>::max()
. хотя вторая более чётко определяет, что хотел сказать поэт.см. Дополнительный_код
Отправить комментарий