Локальная переменная изменяется без манипуляций

#c #variables

#c #переменные

Вопрос:

Я создаю простую программу быстрой сортировки, которая инициализирует пустой массив и запрашивает у пользователей входные данные, чтобы определить, сколько элементов будет отсортировано и какие элементы будут отсортированы.

Проблема, с которой я сталкиваюсь, заключается в том, что локальная переменная изменяется, несмотря на то, что на нее ссылаются только после назначения. Ниже прилагается код.

 int main()
{
    int amount;
    int numbersarray[] = {};
    std::cout << "How many numbers do you want to sort? " << std::endl;
    std::cin >> amount; 
    for(int i = 0; i <= amount; i  ){
        std::cout << "Enter number to be sorted: " << std::endl;
        std::cin >> numbersarray[i]; 
    }
    std::cout <<"Amount to be sorted: " << amount << std::endl;

    for(int i = 0; i <= amount; i  ){
        std::cout << numbersarray[i] << std::endl;
    }
}
  

То, что я ожидаю, произойдет, когда я введу сумму как 5, я должен быть в состоянии ввести 5 элементов в массив, однако вместо этого напечатанная сумма равна 2, а максимальное количество элементов, которые я могу поместить в массив, равно 3.

Ниже приведен результат выполнения.

 How many numbers do you want to sort? 
5
Enter number to be sorted: 
5
Enter number to be sorted: 
2
Enter number to be sorted: 
5
Amount to be sorted: 2
5
2
5
  

Я пытался возиться с оператором for, но я не думаю, что я делаю это правильно, поскольку это не устранило проблему, манипуляция с оператором for, которую я делаю, изменяет условие (т. е. !=, <, <=)

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

1. int numbersarray[] = {}; массивы не являются динамическими в C . Используйте std::vector .

2. Какой компилятор вы используете, поскольку он не должен компилироваться в соответствии со стандартом? Если вы используете GCC, используйте -pedantic-errors в настройках вашего компилятора, чтобы он отклонял этот код.

3. int numbersarray[] = {} не допускается в c (хотя некоторые компиляторы разрешают это по умолчанию как расширение языка). В любом случае, она не содержит элементов, и попытка доступа к одному из них является неопределенным поведением, что означает, что возможно практически все. Это включает в себя, казалось бы, невозможные вещи, такие как несвязанные переменные, спонтанно меняющие значения.

4. @tkausl Имейте в виду, что простого использования std::vector недостаточно. Если она используется в качестве дополнительной замены (просто меняется на std::vector<int> numbersarray; ), она будет скомпилирована и по-прежнему будет вести себя так же. Вам также необходимо использовать emplace_back или другие функции-члены вставки, чтобы правильно вводить новые элементы.

5. @b Установите флажок «педантичный» в разделе «предупреждения» на вкладке «Параметры». Это остановит ее компиляцию.

Ответ №1:

У вас неопределенное поведение. Случиться может все, что угодно. Локальная переменная может измениться без причины, программа может аварийно завершиться, и ваш компьютер может отформатироваться под Linux 6.9

Существует множество проблем. Во-первых, ваша программа недействительна в соответствии со стандартом:

 int numbersarray[] = {};
  

Это недопустимо. Массиву нужен размер:

 constexpr int max_amount = 32;
int numbersarray[max_amount] = {};
  

Если вам нужно, чтобы она была динамической, используйте vector:

 std::vector<int> numbersarray;
numbersarray.resize(amount);
  

Во-вторых, у вас есть другой источник неопределенного поведения:

 //     Iterates too much, numbersarray[amount] is past the end
//             ~~~v~~~~~~~
for(int i = 0; i <= amount; i  ){
    std::cout << "Enter number to be sorted: " << std::endl;
    std::cin >> numbersarray[i]; 
}
  

Это должно быть:

 for(int i = 0; i < amount; i  ){
    std::cout << "Enter number to be sorted: " << std::endl;
    std::cin >> numbersarray[i]; 
}
  

Чтобы избежать недопустимого кода и неопределенного поведения, вам следует включить предупреждения.

Ответ №2:

numbersarray представляет собой массив в стиле C с нулевым размером и не регулирует его размер динамически (большинство компиляторов могут даже не выполнить компиляцию int numbersarray[] = {}; , поскольку пустой инициализатор не разрешен для массива с неопределенным размером).

Запись или чтение ее элементов вызывает неопределенное поведение (которое может быть нарушением доступа, изменением несвязанных переменных и многим другим). Это причина, по которой вы можете увидеть изменение значений локальных переменных. Кто-то другой, использующий тот же код, может получить совершенно другое поведение, поскольку оно не определено.