Предупреждения компилятора
-
21-08-2019 - |
Вопрос
Предположим, у меня есть этот (C ++ или, возможно, C) код:
vector<int> my_vector;
for (int i = 0; i < my_vector.size(); i++) {
my_vector[i] = 0;
}
Мне все равно, правильно ли все сделано.Важная часть содержится в объявлении цикла for.Компилятор выдает несоответствие signed / unsigned для этого, поскольку size() возвращает unsigned int, а не signed .Насколько важно измениться i
в неподписанный?Я по привычке объявляю счетчики циклов целыми числами, но если это потенциальная ошибка, я заставлю себя избавиться от этой привычки.
Решение
Я бы сказал, что это очень важно - вы должны компилировать с предупреждениями в виде ошибок и стремиться исправить все предупреждения.Если вы оставляете подобные проблемы в своем коде, легко приобрести привычку игнорировать предупреждения или позволять ложным срабатываниям, подобным этому, заглушать предупреждения, указывающие на реальные проблемы.
В данном случае, для этой конкретной ошибки, это, вероятно, не имеет большого значения - на 32-разрядной платформе у вас должно быть более 2 миллиардов записей в векторе, прежде чем unsigned превратится в отрицательное значение со знаком.Получение такого вектора исчерпало бы всю вашу память, поэтому, вероятно, невозможно перейти в состояние, в котором несоответствие signed / unsigned имело бы значение.
Другие советы
Технически, i
должно быть vector<int>::size_type
.У вас должно войти в привычку использовать typedef
s в вашем коде:
typedef vector<int> VectorType;
VectorType my_vector;
for (VectorType::size_type i = 0; i < my_vector.size(); i++) {
my_vector[i] = 0;
}
Теперь, если мы изменим его на deque
, мы меняем только одну строку.Даже если это какой-то пользовательский контейнер с дурацким size_type, у вас возникает теплое, нечеткое ощущение, что все будет в порядке.А это дорогого стоит.Даже при использовании простого unsigned / подписанного, есть некоторые сложные проблемы с продвижением при использовании подписанного / неподписанного преобразования, которые неизбежно вернутся к вам.
Это может быть важно в том маловероятном случае, если размер вектора превысит INT_MAX
.Если размер вектора больше максимального значения, которое может быть представлено в виде подписанного int
, тогда ваш цикл никогда не завершится.
Ну, это важно, потому что целые числа со знаком имеют знак, поэтому я мог бы пройти весь путь до отрицательного значения, тогда независимо от того, насколько оно велико, оно все равно было бы меньше, чем size(), у которого нет никакого знака.
11111111 < 10000000
В большинстве случаев вашего примера это не будет иметь значения.но когда ваша программа не работает, первое, что вы делаете (или должны делать), это убедиться в отсутствии предупреждений, так что рисковать не стоит.
убедитесь, что предупреждений как можно меньше.
Как было сказано выше, используйте vector::size_type;или используйте итератор для перебора вашего вектора.Убедитесь, что все ваши собственные предупреждения обрабатываются как ошибки.