Платформо-независимые целочисленные типы

Последнее обновление: 24.01.2024

В зависимости от архитектуры размер базовых типов, таких как int или long может меняться. Например, для типа int стандартом языка Си устанавливается минимальный размер в 2 байта (16 бит), а для типа long - минимальный размер в 4 байта (32 бита). На большинстве современных архитектур int занимает 4 байта, но тем не менее это не обязательное требование. Или к примеру, возьмем следующую простейшую программу:

#include <stdio.h>

int main(void)
{
    printf("sizeof(long) = %zu \n", sizeof(long));
     
    return 0;
}

Даже если мы возьмем только 64-разрядные системы, то окажется, что на Windows long занимает 4 байта, тогда как на Linux - 8 байт.

Для описания применяемых размеров в языке Си используются специальный набор характеристик, который называет модель данных или data model. Существует множество моделей данных, поэтому отмечу только распространенные:

  • LP32: модель 2/4/4 (int - 2 байта, long и указатели по 4 байта). Применяется для 32-разрядных систем в Win16 API

  • ILP32: модель 4/4/4 (int, long и указатели по 4 байта). Применяется для 32-разрядных систем в Win32 API, Unix и Unix-подобных системах (Linux, macOS)

  • LLP6: модель 4/4/8 (int и long по 4 байта, указатель - 8 байт). Применяется для 64-разрядных систем ARM (AArch64) и x86-64 (x64) в Win32 API (также называемом Windows API) или грубо говоря в современном Windows

  • LP64: модель 4/8/8 (int - 4 байта, long и указатели по 8 байт) Применяется для 64-разрядных Unix и Unix-подобных системах (Linux, macOS) (грубо говоря, в современных Linux и MacOS)

Размеры в битах для разных типов в соответствии с выше перечисленными моделями:

Тип данныхСтандарт C LP32 ILP32 LLP64 LP64
char/unsigned charКак минимум 8 8 8 8 8
short/unsigned short int Как минимум 16 16 16 16 16
int / unsigned intКак минимум 16 16 32 32 32
long/unsigned longКак минимум 32 32 32 32 64
long long/unsigned long longКак минимум 64 64 64 64 64

Чтобы уйти от платформенной зависимости начиная со стандарта C99 в язык была добавлена поддержка платформо-независимых числовых типов. Они определены в заголовчном файле stdint.h и имеют названия по следующему шаблону uint|int[размер]_t. В качестве размера указывается количество бит - 8, 16, 32 или 64:

  • int8_t

  • int16_t

  • int32_t

  • int64_t

  • intptr_t (для хранения указателей)

Беззнаковые типы предваряются приставкой u

  • uint8_t

  • uint16_t

  • uint32_t

  • uint64_t

  • uintptr_t (для хранения указателей)

Пример применения:

#include <stdio.h>
#include <stdint.h>


int main(void)
{
    int8_t i8 = -8;
    uint8_t u8 = 8;

    int16_t i16 = -16;
    uint16_t u16 = 16;

    int32_t i32 = -32;
    uint32_t u32 = 32;

    int64_t i64 = -64;
    uint64_t u64 = 64;


    printf("i8 = %d \n", i8);
    printf("u8 = %u \n", u8);

    printf("i16 = %d \n", i16);
    printf("u16 = %u \n", u16);

    printf("i32 = %d \n", i32);
    printf("u32 = %u \n", u32);

    printf("i64 = %lld \n", i64);
    printf("u64 = %llu \n", u64);
     
    return 0;
}

В примере выше для вывода на консоль применяются стандартные встроенные спецификаторы типа %d или %lld. Однако специально для этих типов в заголовочном файле inttypes.h также определены дополнительные макросы:

  • PRI для форматированного вывода (с помощью printf, fprintf и т.д.)

  • SCN для форматированного ввода (scanf, fscanf и т.д.).

Вместе с этими макросами применяются специафикаторы типов:

  • d: для вывода числе в десятичном формате

  • x: в шестнадцатеричном формате

  • o: в восьмеричном формате

  • u: для беззнаковых чисел

  • i: для целых чисел со знаком

Применение

#include <stdio.h>
#include <inttypes.h>


int main(void)
{
    int64_t int64;
    uint64_t uint64;

    printf("Enter signed number: ");
    scanf("%"SCNi64, &int64);

    printf("Enter unsigned number: ");
    scanf("%"SCNu64, &uint64);

    printf("int64 = %" PRIi64 "\n", int64);
    printf("uint64 = %" PRIu64 "\n", uint64);
     
    return 0;
}

Пример ввода:

Enter signed number: -34
Enter unsigned number: 56
int64 = -34
uint64 = 56

Стандартные операции, например, арифметика, производятся также, как и со встроенными типами:

#include <stdio.h>
#include <inttypes.h>


int main(void)
{
    int64_t a = 5;
    int64_t b = 6;

    int64_t c = a + b * a;  // c = 35
    printf("c = %" PRIi64 "\n", c);
     
    return 0;
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850