C ++ адаптивный тип удержания - PullRequest
0 голосов
/ 29 февраля 2020

Недавно я поиграл с дедукцией типов в C ++. При этом я наткнулся на что-то странное. Когда я запускаю этот код:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

Он печатает это:

Factorial of 40 = 0
Size of factorial: 4

Так что очевидно, что произошло переполнение буфера, поэтому factorial равно 0. Но что я не понимаю, так это то, почему auto не адаптировался к чему-то вроде unsigned long long, и почему он оставался int (4 байта)? Есть ли способ исправить это?

Ответы [ 2 ]

3 голосов
/ 29 февраля 2020

В C ++ тип является концепцией только во время компиляции. К тому моменту, когда вы действительно запускаете программу, уже забыто о типах переменных; он не может адаптироваться во время выполнения.

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

1 голос
/ 29 февраля 2020

Так что очевидно, что произошел переполнение буфера

Результат умножения переполняется, но здесь нет переполнения буфера, когда вы записываете больший объем данных в буфер

почему auto не адаптировался к чему-то вроде unsigned long long и почему он оставался как int (4 байта)? Есть ли какой-нибудь способ исправить это?

1 является литералом int, поэтому очевидно, что если вы используете auto factorial = 1;, он создаст переменную int и зарезервирует фиксированный объем памяти для этой переменной , Размер не может быть изменен, потому что если вы увеличите его, он будет перенесен в соседние переменные

Если вам нужна возможность определения размера Dynami c, то обработайте это самостоятельно, выделив память в куче, как контейнеры типа std::vector и std::unordered_map do. Это требует гораздо больше памяти и ресурсов ЦП, что означает, что они не могут применяться к базовым типам POD c, потому что они должны быть быстрыми и максимально приближенными к аппаратному. Если вам нужна большая целочисленная арифметика c, используйте библиотеку произвольной точности , например GMP или Boost.Multiprecision . Или прочитайте теги , , , для получения дополнительной информации

См.

...