Странное присвоение типа для индекса массива в C ++ - PullRequest
0 голосов
/ 10 января 2020

Привет У меня есть пример программы

#include <iostream>

int main() {
    int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

Здесь я получаю вывод 17179869164.

Мой вопрос заключается в том, что значение размера массива не должно принимать отрицательные значения! и если я попытаюсь дать [-5], он выдаст ошибку. но теперь, как я получаю вывод 17179869164.

У меня тоже есть предположение, что -5 преобразуется в значение без знака int 4294967291, а общий размер задается как 17179869164 = 4294967291 * 4 (размер int. Мне нужно было четкое понимание того, как компилятор выполняет этот кусок кода?

Ответы [ 3 ]

1 голос
/ 10 января 2020

Для C ++ массивы переменной длины не предоставляются стандартом, но могут предоставляться расширением компилятора. Для C краткий ответ - стандарт преобразует значение в положительное целое значение, если только оно не является константным выражением - в вашем случае это приводит к использованию значения без знака (использование значения комплимента двух в качестве положительного значения) , В частности:

C11 Standard - 6.7.6.2 Деклараторы массива (p5)

Если размер является выражением, которое не является целочисленным константным выражением: если оно происходит в объявлении в области видимости прототипа функции, она обрабатывается так, как если бы она была заменена на *; в противном случае каждый раз, когда он оценивается, он должен иметь значение больше нуля.

1 голос
/ 10 января 2020

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

Кто-то еще спросил что-то подобное здесь: Объявление массива отрицательной длины

0 голосов
/ 10 января 2020

Я заметил интересное поведение в GodBolt .

Я взял вам код и добавил вторую копию, где a объявлена ​​константой:

#include <iostream>

int foo() {
    int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

int bar() {
    const int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

Затем я бросил в них G CC, Clang и MSV C.

Насколько я знаю, G CC и Clang поддерживают массивы переменной длины (VLA) как «дополнительная функция», и они оба съели foo без единой жалобы. Принимая во внимание, что MSV C, который не поддерживает VLA, жаловался.

С другой стороны, никто из них не принял bar в связи с отрицательным значением a.

Почему? G CC и Кланг не может сказать, что a отрицательно в foo, что я оставлю в качестве вопроса для людей, более сведущих в смелости компилятора, чем я.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...