Почему у меня бесконечный цикл? Простой вопрос, короткий код

#c #for-loop #vector #infinite-loop #implicit-conversion

Вопрос:

Если входной массив пуст, то array.size() должно быть 0. Первое for , что идет от 0 до array.size() - 1 , должно означать , что оно идет от 0 до -1 , верно?

for Тогда это не следует вводить, и функция должна возвращать значение счетчика инверсий, которое было бы 0

Но этого не происходит, и код входит в бесконечный цикл. Почему это происходит?

Вот код:

 #include <vector>
#include <iostream>

using namespace std;

int countInversions(vector<int> array)
{    
    int inversionsCounter = 0;
    for (int i = 0; i < array.size() - 1;   i)
        for (int j = i   1; j < array.size();   j)
            if (array[i] > array[j])
                  inversionsCounter;

    return inversionsCounter;
}

int main()
{
    vector<int> array = {};
    cout << array.size();
    cout << countInversions(array);
}
 

Комментарии:

1. Я верю array.size() - 1 , что переполняется.

2. Сначала решите : C4018: ‘ Это явная подсказка от компилятора. (Я никогда не использую целые числа со знаком для значений, которые всегда должны быть >0, используйте тот же тип, что и возвращаемый array.size()).

3. Пожалуйста, опубликуйте свой фактический код, который вызывает проблему. В опубликованном коде вы вообще не вызываете функцию countInversions .

4. Технически цикл не бесконечен, но он будет длиться довольно долго. array имеет нулевой размер, поэтому array.size() - 1 будет получено наибольшее значение, которое std::size_t может представлять a, которое часто (в зависимости от вашего компилятора и хост-системы) является довольно большим значением (например 4294967295 , в 32-разрядной системе или 18,446,744,073,709,551,615 в 64-разрядной системе).

5. @maverick.01: Как правило, ваш опубликованный код должен быть в состоянии воспроизвести проблему. Читателям вашего вопроса не должно быть необходимости думать о том, какие части вашего кода должны быть раскомментированы, а какие нет, чтобы воспроизвести проблему. Не сразу стало очевидно, что первая часть прокомментированного кода должна оставаться деактивированной, но вторая часть прокомментированного кода должна быть повторно активирована путем раскомментирования. Это затруднило понимание вашего вопроса. Тем временем кто-то другой отредактировал ваш вопрос, чтобы исправить это.

Ответ №1:

Тип возвращаемого значения функции-члена size шаблона класса std::vector -это целочисленный тип без знака, обычно эквивалентный типу size_t .

Таким образом, в состоянии цикла for

 for (int i = 0; i < array.size() - 1;   i)
 

из — за обычных арифметических преобразований оба операнда выражения

 i < array.size() - 1
 

преобразуются в целочисленный тип без знака, соответствующий данному типу std::vector<int>::size_type . В результате выражение array.size() - 1 преобразуется в максимальное значение типа, когда функция-член size возвращает 0.

Вот демонстрационная программа.

 #include <iostream>
#include <iomanip>

int main() 
{
    std::cout << size_t( -1 ) << 'n';
    std::cout << std::boolalpha << ( 0 < size_t( -1 ) ) << 'n';    
    
    return 0;
}
 

Его выход составляет

 18446744073709551615
true
 

Поэтому, когда функция-член size возвращает 0, на самом деле у вас есть цикл, подобный этому

 for (int i = 0; i < 18446744073709551615;   i)
 

Вместо типа int вы должны использовать, по крайней мере, тип size_t для индексов. И внешняя петля должна выглядеть так

 for ( size_t i = 0; i < array.size();   i )
 

Ответ №2:

Тип возвращаемого значения для метода size() в vector<> -<> size_t , целочисленное значение без знака — часто просто unsigned int . Этот тип , size_t , не имеет знака и не может содержать отрицательных чисел. В большинстве случаев компилятор предупредит вас об этом.

Однако, когда пришло время выполнить код, компилятор заменяет форму «дополнения» целого числа со знаком -1 (вычисляется по размеру() — 1 ) на size_t тип (без знака).

Это число со знаком -1 часто бывает очень большим, когда предпринимается попытка представить его как число без подписи. Большая часть специфики здесь зависит от вашей конкретной машины и деталей компилятора.

Это означает, что ваш внешний цикл for for (int i = 0; i < array.size() - 1; i) выполняется не в бесконечном цикле, а в очень длинном.

Ответ №3:

приведите array.size() к int, в противном случае похожему …

 (int)array.size()