Unsigned int диапазон: Система типов C++ | Microsoft Learn

Диапазоны типов данных | Microsoft Learn

Twitter LinkedIn Facebook Адрес электронной почты

  • Статья
  • Чтение занимает 2 мин

32-разрядные и 64-разрядные компиляторы Microsoft C++ распознают типы в таблице далее в этой статье.

  • int (unsigned int)

  • __int8 (unsigned __int8)

  • __int16 (unsigned __int16)

  • __int32 (unsigned __int32)

  • __int64 (unsigned __int64)

  • short (unsigned short)

  • long (unsigned long)

  • long long (unsigned long long)

Если имя начинается с двух символов подчеркивания (__), тип данных является нестандартным.

Диапазоны, представленные в следующей таблице, включают указанные значения.

Имя типаБайтыДругие именаДиапазон значений
int4signedОт -2 147 483 648 до 2 147 483 647
unsigned int4unsignedОт 0 до 4 294 967 295
__int81charОт -128 до 127
unsigned __int81unsigned char
От 0 до 255
__int162short, short int, signed short intОт -32 768 до 32 767
unsigned __int162unsigned short, unsigned short intОт 0 до 65 535
__int324signed, signed int, intОт -2 147 483 648 до 2 147 483 647
unsigned __int324unsigned, unsigned intОт 0 до 4 294 967 295
__int648long long,
signed long long
От -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
unsigned __int648unsigned long longОт 0 до 18 446 744 073 709 551 615
bool1нетfalse или true
char1нетОт -128 до 127 по умолчанию

От 0 до 255 при компиляции с помощью /J

signed char1нетОт -128 до 127
unsigned char1нетОт 0 до 255
short2short int, signed short int
От -32 768 до 32 767
unsigned short2unsigned short intОт 0 до 65 535
long4long int, signed long intОт -2 147 483 648 до 2 147 483 647
unsigned long4unsigned long intОт 0 до 4 294 967 295
long long8нет (но эквивалентно __int64)От -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
unsigned long long8нет (но эквивалентно unsigned __int64)От 0 до 18 446 744 073 709 551 615
enum
непостояннонет
float4нет3,4E +/- 38 (7 знаков)
double8нет1,7E +/- 308 (15 знаков)
long doubleто же, что и doubleнетТо же, что double
wchar_t2__wchar_tОт 0 до 65 535

В зависимости от характера использования переменная типа __wchar_t обозначает расширенный символьный или многобайтовый символьный тип. Чтобы указать константу расширенного символьного типа, перед символьной или строковой константой следует использовать префикс

L .

signed и unsigned — это модификаторы, которые можно использовать с любым целочисленным типом, кроме типа bool. Обратите внимание, что char, signed charи unsigned char — это три разных типа, предназначенных для механизмов, подобных перегрузке и шаблонам.

Размер типов int и unsigned int — 4 байта. Однако переносимый код не должен зависеть от размера int , поскольку языковой стандарт позволяет варьировать его в зависимости от реализации.

C и C++ в Visual Studio также поддерживают целочисленные типы с указанием размера. Дополнительные сведения см. в разделах __int8, __int16, __int32, __int64 и Integer Limits.

Дополнительные сведения об ограничениях размеров каждого типа см. в разделе Встроенные типы.

Диапазон перечисляемых типов зависит от контекста языка и указанных флажков компилятора. Дополнительные сведения см. в статьях Объявления перечислений C и Объявления перечислений C++.

Ключевые слова
Встроенные типы

Типы данных — Основы С++

C++ — язык со статической типизацией. У каждой переменной на этапе компиляции должен быть чётко определённый тип данных. Про каждый тип данных заранее известно, сколько места в памяти занимает переменная такого типа.

В этой главе мы познакомимся с некоторыми базовыми типами данных и с понятием области видимости переменных.

Области видимости

В С++ существует понятие области видимости (scope) переменной. Эта область ограничивается блоком кода, в котором переменная определена. Рассмотрим пример:

#include <iostream>
int a = 1;  // глобальная переменная
int main() {
    int b = 2;  // локальная переменная
    {
        int c = 3;  // локальная переменная внутри блока
        std::cout << a << " " << b << " " << c << "\n";  // корректно
    }
    // Эта строчка не скомпилируется,
    // так как переменная c не определена в данной области:
    std::cout << c << "\n";
}

В этом примере есть три области:

  • глобальная, в которой определена переменная a;
  • тело функции main, в которой определена переменная b;
  • внутренний блок, в котором определена переменная c.

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

Рассмотрим пример:

#include <iostream>
int main() {
    int x = 1;
    std::cout << x << "\n";  // напечатает 1
    {
        int x = 2;  // новая переменная, к предыдущему x не имеет отношения
        std::cout << x << "\n";  // напечатает 2
    }
    std::cout << x << "\n";  // снова напечатает 1
}

Инициализация локальных переменных

Локальные переменные простых типов, таких как int, не инициализируются по умолчанию нулём. Компилятор просто выделяет для них байты в стековой памяти, но при этом он не обязан как-либо их заполнять. Это один из принципов C++: мы не должны платить за то, что не используем.

Следующий фрагмент кода может напечатать всё что угодно:

#include <iostream>
int main() {
    int x;
    std::cout << x << "\n";  // неопределённое поведение!
    int y;
    std::cin >> y;  // а это допустимый сценарий
}

Компиляторы g++ и clang++ обычно дают предупреждения о чтении неинициализированных переменных при использовании опции -Wall или -Wuninitialized:

$ clang++ -Wall program.
= 0 1 warning generated.

Заметим, что std::string является сложным типом и переменные такого типа всегда по умолчанию инициализируются пустой строкой. Поэтому нет необходимости писать std::string s = "";. Пишите просто std::string s;.

Простые типы данных

С типом int мы уже знакомы. Рассмотрим другие фундаментальные типы данных в С++. Это так называемые интегральные типы и типы для вещественных чисел.

int main() {
    char c = '1';    // символ
    bool b = true;   // логическая переменная, принимает значения false и true
    int i = 42;      // целое число (занимает, как правило, 4 байта)
    short int i = 17;            // короткое целое (занимает 2 байта)
    long li = 12321321312;       // длинное целое (как правило, 8 байт)
    long long lli = 12321321312; // длинное целое (как правило, 16 байт)
    float f = 2.71828;           // дробное число с плавающей запятой (4 байта)
    double d = 3. 141592;         // дробное число двойной точности (8 байт)
    long double ld = 1e15;       // длинное дробное (как правило, 16 байт)
}

Обратите внимание, что символы, в отличие от строк (то есть массивов символов), записываются в апострофах, а не в кавычках. В примере выше мы записываем в переменную c символ единицы. Фактически в памяти хранится ASCII-код этого символа, который равен 49.

Напомним, что каждый тип данных занимает заранее известное количество байтов памяти. Стандарт языка С++ не накладывает жёстких ограничений на размеры типов, они могут отличаться для разных платформ и компиляторов.

О том, что делать с этой особенностью, мы расскажем ниже. А пока отметим, что узнать размер переменной или типа на этапе компиляции можно с помощью оператора sizeof.

Например, на 64-битной Linux-системе компилятор clang++ использует такие размеры для типов:

int main() {
    std::cout << "char: " << sizeof(char) << "\n";                 //  1
    std::cout << "bool: " << sizeof(bool) << "\n";                 //  1
    std::cout << "short int: " << sizeof(short int) << "\n";       //  2 (по стандарту >= 2)
    std::cout << "int: " << sizeof(int) << "\n";                   //  4 (по стандарту >= 2)
    std::cout << "long int: " << sizeof(long int) << "\n";         //  8 (по стандарту >= 4)
    std::cout << "long long int: " << sizeof(long long) << "\n";   //  8 (по стандарту >= 8)
    std::cout << "float: " << sizeof(float) << "\n";               //  4
    std::cout << "double: " << sizeof(double) << "\n";             //  8
    std::cout << "long double: " << sizeof(long double) << "\n";   // 16
}

Размеры стандартных типов

По умолчанию числовые типы – знаковые. 32 — 1 }

Минимальное и максимальное значение, помещающееся в данный числовой тип, можно получить так:

#include <iostream>
#include <limits>  // необходимо для numeric_limits
int main() {
    // посчитаем для типа int:
    std::cout << "minimum value: " << std::numeric_limits<int>::min() << "\n"
              << "maximum value: " << std::numeric_limits<int>::max() << "\n";
}

Данный пример на 64-битной Linux-системе напечатает:

minimum value: -2147483648
maximum value: 2147483647

Приведённые выше примеры вывода оператора sizeof верны для 64-битных архитектур, которые на сегодняшний день распространены повсеместно. Однако если бы мы скомпилировали и запустили такую программу на компьютере с 32-битной архитектурой, то получили бы другие результаты. Например, sizeof(long int) стал бы равен 4, в то время как на современных компьютерах мы получили бы 8. Также бывают встраиваемые системы, под которые тоже можно писать на С++. Там битность архитектуры может быть ещё меньше, чем 32.

В заголовочном файле cstdint стандартной библиотеки имеются целочисленные типы с фиксированным размером:

  • int8_t / uint8_t
  • int16_t / uint16_t
  • int32_t / uint32_t
  • int64_t / uint64_t

Число в имени типа означает количество бит, используемых для хранения в памяти. Например, int32_t содержит 32 бита (4 байта) и часто соответствует типу int. Если система не поддерживает какой-то тип, то программа с ним просто не скомпилируется.

Переполнение целочисленных типов

Стандартные числовые типы имеют ограниченный размер и ограниченное множество допустимых значений. При арифметических операциях над числами таких типов может возникнуть переполнение — ситуация, когда результат операции не помещается в тип:

#include <iostream>
int main() {
    unsigned int a = 123456;  // на 64-битной платформе sizeof(a) == 4
    // Произведение a * a не помещается в 4 байта, так как оно больше 2^32
    std::cout << a * a << "\n";
}

В этом примере выражение a * a будет иметь тот же тип, что и аргументы, поскольку результат не помещается в него целиком. То, что на самом деле будет вычислено, зависит от знаковости типа.

Беззнаковые типы можно спокойно переполнять: вычисления будут производиться по модулю соответствующей степени двойки. Другими словами, будут учтены только младшие биты результата:

int main() {
    unsigned int x = 0;      // на 64-битной платформе sizeof(x) == 4
    unsigned int y = x - 1;  // 4294967295, то есть 2**32 - 1
    unsigned int z = y + 1;  // 0
}

Наоборот, для знаковых типов переполнение приводит к так называемому неопределённому поведению (UB, undefined behavior).

Такая ситуация не считается ошибкой компиляции (в самом деле, на стадии компиляции значения переменных могут быть ещё неизвестны). Но в этом случае стандарт С++ перестаёт что-либо гарантировать по поводу поведения программы. Компиляторы могут использовать такие случаи для оптимизации программ, полагаясь на то, что разработчики пишут код корректно и никогда не допускают неопределённого поведения. Далее нам встретятся и другие случаи неопределённого поведения.

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

Арифметические операции

Бинарные операции +, - и * работают для чисел стандартным образом. Результат операции деления /, применённой к целым числам, всегда округляется в сторону нуля. Таким образом, для положительных чисел операция / возвращает неполное частное. Остаток от деления целых чисел можно получить с помощью операции %.

int main() {
    int a = 7, b = 3;
    int q = a / b;  // 2
    int r = a % b;  // 1
}

Если при делении нужно получить обычное частное, то один из аргументов нужно привести к вещественному типу (например, double) с помощью оператора static_cast:

int main() {
    int a = 6, b = 4;
    double q = static_cast<double>(a) / b;  // 1. 5
}

Можно было бы написать чуть более кратко: double q = a * 1.0 / b;. Тогда преобразование аргументов произошло бы неявно.

Арифметические операции над символами, а также сравнение символов друг с другом — это фактически операции над их ASCII-кодами:

#include <iostream>
int main() {
    char c = 'A';
    c += 25;  // увеличиваем ASCII-код символа на 25
    std::cout << c << "\n";  // Z
}
Таблица ASCII с шестнадцатеричными кодами символов. Слева указана старшая шестнадцатеричная цифра, справа — младшая. Цветом выделены так называемые управляющие символы, обычно не имеющие графического представления.

Операция + применительно к строкам означает конкатенирование (то есть склейку). Это пример перегрузки операции: изначальному оператору сложения в стандартной библиотеке для строки придали новый смысл.

#include <string>
int main() {
    std::string a = "Hello, ";
    std::string b = " world!";
    std::string c = a + b;  // Hello, world!
}

Для каждой бинарной операции (например, +) есть версия со знаком равенства (+=) для случая, когда левый аргумент совпадает с переменной, которой присваивается результат:

int main() {
    int x = 5;
    x += 3;  // x = x + 3
    x *= x;  // x = x * x
}

Наконец, имеются операторы ++ и -- для увеличения или уменьшения переменной на единицу. Они бывают префиксные и постфиксные. Отличие состоит в значении выражения, которое будет вычисляться при применении такого оператора. Мы рассмотрим это позже, а пока привыкнем по умолчанию использовать префиксный оператор для обычных чисел:

int main() {
    int x = 5;
    ++x;  // 6
    --x;  // снова 5
}

Числа с плавающей точкой

В языке C++ существуют три встроенных типа для записи дробных чисел: float (4 байта), double (8 байт) и long double (16 или 8 байт, в зависимости от платформы). В большинстве случаев рекомендуется использовать тип double. Тип float разумно использовать там, где обрабатываются огромные массивы чисел, и возникает необходимость экономить память.

Как правило, хранение дробных чисел в С++ основано на стандарте IEEE 754. Число представляется в виде двоичной дроби в экспоненциальной записи: отдельно хранятся бит знака, порядок и мантисса.

Такое представление выгодно отличается от чисел с фиксированной точкой, где хранится фиксированное количество разрядов. Оно позволяет, хотя и с разной степенью точности, представлять числа, отличающиеся на порядки.

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

Автоматический вывод типа

Компилятор C++ умеет автоматически выводить тип переменной по значению, которое ей присваивается. Для этого вместо типа надо написать ключевое слово auto:

int main() {
    auto x = 42;  // int
    auto pi = 3.14159;  // double
}

Ключевое слово auto позволяет сократить код и не выписывать сложные типы (нам встретятся дальше монстры вроде std::unordered_multimap<Key, Value>::const_iterator). Важно подчеркнуть, что точный тип переменной всё равно становится известен в момент компиляции.

При использовании auto со строками нужно быть осторожным. Важно знать, что конструкция auto s = "hello" выведет низкоуровневый тип const char * (указатель на неизменяемый набор символов в памяти), а не тип-обёртку std::string.

Точные правила вывода типов похожи на правила вывода шаблонных параметров, с которыми мы познакомимся в главе про шаблоны.

диапазонов типов данных | Microsoft Узнайте

Редактировать

Твиттер LinkedIn Фейсбук Электронная почта

  • Статья
  • 2 минуты на чтение

32-разрядные и 64-разрядные компиляторы Microsoft C++ распознают типы, указанные в таблице далее в этой статье.

  • целое число ( целое число без знака )

  • __int8 ( без знака __int8 )

  • __int16 ( без знака __int16 )

  • __int32 ( без знака __int32 )

  • __int64 ( без знака __int64 )

  • короткий ( короткий без знака )

  • длинный ( длинный без знака )

  • длинный длинный ( беззнаковый длинный длинный )

Если его имя начинается с двух знаков подчеркивания ( __ ), тип данных нестандартен.

Диапазоны, указанные в следующей таблице, включают включительно.

Название типа байт Другие названия Диапазон значений
внутр. 4 подписанный -2 147 483 648 до 2 147 483 647
целое число без знака 4 без знака от 0 до 4 294 967 295
__int8 1 символ от -128 до 127
без знака __int8 1 беззнаковый символ от 0 до 255
__int16 2 короткий , короткий целый , подписанный короткий целый от -32 768 до 32 767
без знака __int16 2 беззнаковое короткое , беззнаковое короткое целое от 0 до 65 535
__int32 4 подписанный , подписанный внутр. , внутр. -2 147 483 648 до 2 147 483 647
без знака __int32 4 без знака , целое число без знака от 0 до 4 294 967 295
__int64 8 длинный длинный , подписанный длинный длинный -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
без знака __int64 8 без знака длинный длинный от 0 до 18 446 744 073 709 551 615
логический 1 нет ложь или правда
символ 1 нет от -128 до 127 по умолчанию

от 0 до 255 при компиляции с использованием /J

знаковый символ 1 нет от -128 до 127
беззнаковый символ 1 нет от 0 до 255
короткий 2 короткое целое , подписанное короткое целое от -32 768 до 32 767
короткий без знака 2 короткое целое без знака от 0 до 65 535
длинный 4 длинное целое , подписанное длинное целое -2 147 483 648 до 2 147 483 647
длинный без знака 4 длинное целое без знака от 0 до 4 294 967 295
длинный длинный 8 нет (но эквивалентно __int64 ) -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
без знака длинный длинный 8 нет (но эквивалентно unsigned __int64 ) от 0 до 18 446 744 073 709 551 615
перечисление варьируется нет
поплавок 4 нет 3. 4E +/- 38 (7 цифр)
двойной 8 нет 1.7E +/- 308 (15 цифр)
длинный двойной аналогично двойной нет То же, что и двойной
wchar_t 2 __wchar_t от 0 до 65 535

В зависимости от того, как она используется, переменная __wchar_t обозначает либо широкосимвольный, либо многобайтовый тип символов. Используйте префикс L перед символьной или строковой константой для обозначения широкосимвольной константы.

signed и unsigned — это модификаторы, которые можно использовать с любым целочисленным типом, кроме bool . Обратите внимание, что char , signed char и unsigned char являются тремя различными типами для таких механизмов, как перегрузка и шаблоны.

Типы int и unsigned int имеют размер четыре байта. Однако переносимый код не должен зависеть от размера int , потому что стандарт языка допускает, что это зависит от реализации.

C/C++ в Visual Studio также поддерживает целочисленные типы с размером. Дополнительные сведения см. в разделе __int8, __int16, __int32, __int64 и целочисленные ограничения.

Дополнительные сведения об ограничениях размеров каждого типа см. в разделе Встроенные типы.

Диапазон перечисляемых типов зависит от контекста языка и указанных флагов компилятора. Дополнительные сведения см. в разделе Объявления и перечисления C.

См.

также

Ключевые слова
Встраиваемые модели

Обратная связь

Просмотреть все отзывы о странице

Беззнаковые целые типы | Документация Kotlin

Помимо целочисленных типов, Kotlin предоставляет следующие типы для целых чисел без знака:

  • 964 — 1

Типы без знака поддерживают большинство операций своих аналогов со знаком.

Числа без знака реализованы как встроенные классы с единственным свойством хранения соответствующего типа аналога со знаком той же ширины. Тем не менее, изменение типа с беззнакового на подписанный аналог (и наоборот) является бинарным изменением , несовместимым с .

Беззнаковые массивы и операции над ними находятся в стадии бета-тестирования. Они могут быть изменены несовместимо в любое время. Требуется согласие (подробности см. ниже).

Same as for primitives, each of unsigned type has corresponding type that represents arrays of that type:

  • UByteArray : an array of unsigned bytes

  • UShortArray : an array of unsigned shorts

  • UIntArray : массив целых чисел без знака

  • ULongArray : массив длинных чисел без знака0024 Массив класса без накладных расходов.

    При использовании массивов без знака вы получите предупреждение о том, что эта функция еще не стабильна. Чтобы удалить предупреждение, включите аннотацию @ExperimentalUnsignedTypes . Вам решать, должны ли ваши клиенты явно соглашаться на использование вашего API, но имейте в виду, что неподписанные массивы не являются стабильной функцией, поэтому API, который их использует, может быть нарушен из-за изменений в языке. Узнайте больше о требованиях для подписки.

    Диапазоны и последовательности поддерживаются для UInt и ULong классами UIntRange , UIntProgression , ULongRange и ULongProgression . Вместе с целочисленными типами без знака эти классы стабильны.

    Чтобы упростить использование целых чисел без знака, Kotlin предоставляет возможность пометить целочисленный литерал суффиксом, указывающим на определенный беззнаковый тип (аналогично Float или Long ): 9Тег 0003

    • u и U предназначен для беззнаковых литералов. Точный тип определяется на основе ожидаемого типа. Если ожидаемый тип не указан, компилятор будет использовать UInt или ULong в зависимости от размера литерала:

      val b: UByte = 1u // UByte, указан ожидаемый тип val s: UShort = 1u // UShort, указан ожидаемый тип val l: ULong = 1u // ULong, указан ожидаемый тип val a1 = 42u // UInt: ожидаемый тип не указан, константа вписывается в UInt val a2 = 0xFFFF_FFFF_FFFFu // ULong: ожидаемый тип не указан, константа не помещается в UInt

    • uL и UL явно помечают литерал как unsigned long:

      val a = 1UL // ULong, несмотря на то, что ожидаемый тип не указан и константа подходит для UInt В случае беззнаковых чисел используется полный битовый диапазон целого числа для представления положительных значений.
      Например, для представления шестнадцатеричных констант, которые не подходят для типов со знаком, таких как цвет, в 32-битном формате AARRGGBB :

      класс данных Color (представление val: UInt) val yellow = Color(0xFFCC00CCu)

      Вы можете использовать числа без знака для инициализации массивов байтов без явного указания toByte() литеральные приведения:

      val byteOrderMarkUtf8 = ubyteArrayOf(0xEFu, 0xBBu, 0xBFu) API.

Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *