Что значит int в c

What does int() do in C++?

The following code can pass compiling and will print 0 on the console. I saw similar code in STL. Does type int in C++ have a constructor? Is int() a call of some defined function?

Peter Mortensen's user avatar

3 Answers 3

In this context,

it value-initializes a , so that it holds value 0 . This syntax does not require the presence of a constructor for built-in types such as int .

Note that this form is necessary because the following is parsed as a function declaration, rather than an initialization:

In C++11 you can achieve value initialization with a more intuitive syntax:

Edit in this particular case, there is little benefit from using 1) or 3) over

first, we start with this syntax:

this syntax is called value initialization of a variableName, or in other word we say a variableName is zero initialized.

But, what is the meaning of the value initialization.

if the type of a variableName is a built-in/scalar type like (int, char, . ), value initialization mean that a variableName is initialized with the value zero.

and if the type is a complex type like (classes, structs, . ) mean that a variableName is initialized by calling its default constructor.

C2017/Типы данных в C

Целочисленные типы данных используются для хранения целых чисел (тип char также используется для хранения ASCII-символов). Все размеры диапазонов представленных ниже типов данных минимальны и на отдельно взятой платформе могут быть больше.

Стандарт не требует, чтобы два разных типа имели разный размер: sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) . Таким образом, даже типы char и long могут иметь одинаковый размер, но такие платформы очень редки. Стандарт гарантирует, что sizeof(char) всегда равен 1.

Минимальный диапазон значений целых типов по стандарту определяется с [math]-(2^N-1)[/math] по [math]2^N-1[/math] , где [math]N[/math] — разрядность типа. Реализация компиляторов может расширять этот диапазон по своему усмотрению. Отметим, что такие ограничения позволяют использовать то или иное представление знаковых чисел:

  • дополнительный код (two’s complement) — для отрицательного числа код можно получить инвертированием его двоичного модуля и прибавлением к инверсии единицы
  • обратный код (ones’ complement) — двоичный код отрицательного целого числа состоит из одноразрядного кода знака (двоичной цифры 1), за которым следует ( [math]n−1[/math] )-разрядное двоичное число, представляющее собой инвертированное ( [math]n−1[/math] )-разрядное представление модуля числа
  • прямой код (sign and magnitude method) — знаковый бит и затем модуль числа без инвертирования.

Отдельное внимание стоит уделить типу char . Формально это отдельный тип, но фактически char эквивалентен либо signed char , либо unsigned char , в зависимости от компилятора.

Для того, чтобы избежать путаницы между размерами типов стандарт C99 ввел новые типы данных, описанные в файле stdint.h. Среди них такие типы как: intN_t , int_leastN_t , int_fastN_t , где N = 8, 16, 32 или 64. Приставка least- обозначает минимальный тип, способный вместить N бит, приставка fast- обозначает тип размером не менее 16 бит, работа с которым наиболее быстрая на данной платформе. Типы без приставок обозначают типы с фиксированном размером, равным N бит.

Типы с приставками least- и fast- можно считать заменой типам int , short , long , с той лишь разницей, что первые дают программисту выбрать между скоростью и размером.

Тип данных Размер Минимальный диапазон значений Первое появление
signed char минимум 8 бит от -127 (= -(2 8 -1)) до 127 K&R C
unsigned char минимум 8 бит от 0 до 255 (=2 8 -1) K&R C
char минимум 8 бит от -127 до 127 или от 0 до 255 в зависимости от компилятора K&R C
short int минимум 16 бит от -32,767 (= -(2 15 -1)) до 32,767 K&R C
unsigned short int минимум 16 бит от 0 до 65,535 (= 2 16 -1) K&R C
int минимум 16 бит от -32,767 до 32,767 K&R C
unsigned int минимум 16 бит от 0 до 65,535 (= 2 16 -1) K&R C
long int минимум 32 бита  от -2,147,483,647 до 2,147,483,647 K&R C
unsigned long int минимум 32 бита  от 0 до 4,294,967,295 (= 2 32 -1) K&R C
long long int минимум 64 бита от -9,223,372,036,854,775,807 до 9,223,372,036,854,775,807 C99
unsigned long long int минимум 64 бита от 0 до 18,446,744,073,709,551,615 (= 2 64 -1) C99
int8_t 8 бит от -127 до 127 C99
uint8_t 8 бит от 0 до 255 (=2 8 -1) C99
int16_t 16 бит от -32,767 до 32,767 C99
uint16_t 16 бит от 0 до 65,535 (= 2 16 -1) C99
int32_t 32 бита от -2,147,483,647 до 2,147,483,647 C99
uin32_t 32 бита от 0 до 4,294,967,295 (= 2 32 -1) C99
int64_t 64 бита от -9,223,372,036,854,775,807 до 9,223,372,036,854,775,807 C99
uint64_t 64 бита от 0 до 18,446,744,073,709,551,615 (= 2 64 -1) C99
Ошибки

Memsize-типы

Для представления величин, связанных с памятью, в C есть typedef’ы size_t и ptrdiff_t. Размер определяется архитектурой процессора.

size_t — беззнаковый тип для представления размера любого объекта (включая массив). Он способен хранить в себе размер максимального массива, который может быть теоретически выделен в рамках данной архитектуры.

Оператор sizeof возвращает результат типа size_t. Для size_t гарантируется, что он как минимум 16-битный.

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

Модели данных

Под моделью данных следует понимать соотношения размерностей типов, принятых в рамках среды разработки на С.

Примеры приведены в таблице.

Data-model.png

Вещественные типы

Стандартом гарантируется только, что sizeof(float) <= sizeof(double) <= sizeof(long double) .

На большинстве платформ применяются типы с плавающей точкой в соответствии со стандартом IEEE 754.

Логический тип

В языке C в стандарте C99 введён тип _Bool.

Массивы

Для каждого типа T, кроме void и типов функций, существует тип «массив из элементов N типа T». Массив — это коллекция значений одного типа, хранящихся последовательно в памяти. Массив размера N индексируется целым числом от 0 до N-1.

Массивы могут быть инициализированы с помощью списка инициализации, но не могут быть присвоены друг к другу.

В C99 добавлены динамические многомерные массивы:

Указатели

Для любого типа T существует тип «указатель на T».

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

Поскольку указатель — тоже тип переменной, правило «для любого типа T» выполняется и для них: можно объявлять указатели на указатели. К примеру, можно пользоваться int*** :

Существуют также указатели на массивы и на функции. Указатели на массивы имеют следующий синтаксис:

pc  — массив указателей, занимающий 10 * sizeof(char*) байт (на распространённых платформах — обычно 40 или 80 байт), а pa  — это один указатель; занимает он обычно 4 или 8 байт, однако позволяет обращаться к массиву, занимающему 10 байт: sizeof(pa) == sizeof(int*) , но sizeof(*pa) == 10 * sizeof(char) . Указатели на массивы отличаются от указателей на первый элемент арифметикой. Например, если указатели pa указывает на адрес 2000, то указатель pa+1 будет указывать на адрес 2010.

Структуры

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

При инициализации элементов структуры надо иметь в виду следующий момент:

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

Важное отличие между С и C++.

В C++ можно писать

В C нужно писать

Так сделано специально. Названия структур находятся в отдельном пространстве имён. Их всего четыре вида:

  • названия меток (для goto);
  • теги (названия структур, объединений, перечислений);
  • члены структур и объединений;
  • все прочие идентификаторы.

Это позволяет, например, назвать переменную так же, как называется структура.

Или же можно сделать typedef:

Доступ к элементам структуры осуществляется с помощью оператора .. Для обращения к полям структуры по указателю существует оператор «стрелочка» ->, синонимичный предыдущей записи: (*p).x — то же самое, что и p->x.

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

Структуры не всегда занимают число байт, равное сумме байт их элементов. Компилятор обычно выравнивает элементы. The Lost Art of C Structure Packing

Адрес памяти первого поля структуры равен адресу самой структуры.

Объединения

Доступ к одним и тем же данным разными способами:

Т. н. type punning (каламбур типизации)

Стандартом C99 это разрешается (в отличие от приведения указателей разных типов).

If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

Свод правил по работе с целыми числами в C/C++

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

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

Типы данных

Базовые целочисленные типы

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

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

  • char : минимум 8 бит в ширину;
  • short : минимум 16 бит и при этом не меньше char ;
  • int : минимум 16 бит и при этом не меньше short ;
  • long : минимум 32 бит и при этом не меньше int ;
  • long long : минимум 64 бит и при этом не меньше long .

Наличие знака

  • Стандартный сhar может иметь знак или быть беззнаковым, что зависит от реализации.
  • Стандартные short , int , long и long long идут со знаком. Беззнаковыми их можно сделать, добавив ключевое слово unsigned .
  • Числа со знаком можно кодировать в двоичном формате в виде дополнительного кода, обратного или как величину со знаком. Это определяется реализацией. Заметьте, что обратный код и величина со знаком имеют различные шаблоны битов для отрицательного нуля и положительного, в то время как дополнительный код имеет уникальный нуль.
  • Символьные литералы (в одинарных кавычках) имеют тип ( signed ) int в C, но ( signed или unsigned ) char в C++.

Дополнительные правила

  • sizeof(char) всегда равен 1, независимо от битовой ширины char .
  • Битовая ширина не обязательно должна отличаться. Например, допустимо использовать char , short и int , каждый шириной в 32 бита.
  • Битовая ширина должна быть кратна 2. Например, int может иметь ширину 36 бит.
  • Есть разные способы написания целочисленного типа. К примеру, в каждой следующей строке перечислен набор синонимов:
    • int , signed , signed int , int signed ;
    • short , short int , short signed , short signed int ;
    • unsigned long long , long unsigned int long , int long long unsigned .

    Типы из стандартных библиотек

    • size_t (определен в stddef.h) является беззнаковым и содержит не менее 16 бит. При этом не гарантируется, что его ширина будет как минимум равна int .
    • ptrdiff_t (определен в stddef.h) является целочисленным типом со знаком. Вычитание двух указателей будет давать этот тип. При этом не стоит ожидать, что вычитание двух указателей даст int .
    • В stdint.h определена конкретная ширина типов: uint8_t , int8_t , 16 , 32 и 64 . Будьте внимательны к операциям, подразумевающим продвижение типов. Например, uint8_t + uint8_t даст int (со знаком и шириной не менее 16 бит), а не uint8_t , как можно было предположить.

    Преобразования

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

    Как происходит преобразование?

    Главный принцип в том, что, если целевой тип может содержать значение исходного типа, то это значение семантически сохраняется.

    • Когда исходный тип расширяется до целевого типа с аналогичной знаковой характеристикой (например, signed char -> int или unsigned short -> unsigned long ), каждое исходное значение после преобразования сохраняется.
    • Даже если исходный и целевой типы имеют разные диапазоны, все значения в их пересекающейся части будут сохранены. Например, int , содержащий значение в диапазоне [0, 255] , будет без потерь преобразован в unsigned char .
    • При преобразовании в беззнаковый тип новое значение равняется старому значению по модулю 2 целевая ширина в битах . Объяснение:
      • Если исходный тип беззнаковый и шире целевого, тогда старшие биты отбрасываются.
      • Если исходный тип имеет знак, тогда в процессе преобразования берется исходное значение, и из него/к нему вычитается/прибавляется 2 целевая ширина в битах до тех пор, пока новое значение не впишется в диапазон целевого типа. Более того, если число со знаком представлено в дополнительном коде, то в процессе преобразования старшие биты отбрасываются, как и в случае с беззнаковыми числами.
      • Если исходное значение вписывается в диапазон целевого типа, тогда процесс преобразования (например, расширение знака) производит целевое значение, семантически равное исходному.
      • Если же оно не вписывается, тогда поведение будет определяться реализацией и может вызвать исключение (к примеру, прерывание из-за переполнения).

      Арифметика

      Продвижение/преобразование

        Унарный арифметический оператор применяется только к одному операнду. Примеры: — ,
      • В реализации присутствуют 16-битный short и 24-битный int . Если переменные x и y имеют тип unsigned short , то операция x & y продвигает оба операнда до signed int .
      • В реализации присутствуют 32-битный char и 32-битный int . Если переменные x и y имеют тип unsigned char , то операция x – y продвигает оба операнда до unsigned int .
      • (long) + (long) → (long) ;
      • (unsigned int) * (int) → (unsigned int) ;
      • (unsigned long) / (int) → (unsigned long) ;
      • если int является 32-битным, а long 64-битным: (unsigned int) % (long) → (long) ;
      • если int и long оба являются 32-битными: (unsigned int) % (long) → (unsigned long) .

      Неопределенное поведение

      Знаковое переполнение:

      • При выполнении арифметических операций над целочисленным типом переполнение считается неопределенным поведением (UB). Такое поведение может вызывать верные, несогласованные и/или неверные действия как сразу, так и в дальнейшем.
      • При выполнении арифметики над беззнаковым целым (после продвижений и преобразований) любое переполнение гарантированно вызовет оборот значения. Например, UINT_MAX + 1 == 0 .
      • Выполнение арифметики над беззнаковыми целыми фиксированного размера может привести к едва уловимым ошибкам. Например:
        • Пусть uint16_t = unsigned short , и int равен 32-битам. Тогда uint16_t x=0xFFFF , y=0xFFFF , z=x*y ; x и y будут продвинуты до int , и x * y приведет к переполнению int , вызвав неопределенное поведение.
        • Пусть uint32_t = unsigned char , и int равен 33-битам. Тогда uint32_t x=0xFFFFFFFF , y=0xFFFFFFFF , z=x+y ; x и y будут продвинуты до int , и x + y приведет к переполнению int , то есть неопределенному поведению.
        • Чтобы обеспечить безопасную арифметику с беззнаковыми целыми, нужно либо прибавить 0U , либо умножить на 1U в качестве пустой операции. Например: 0U + x + y или 1U * x * y . Это гарантирует, что операнды будут продвинуты как минимум до ранга int и при этом останутся без знаков.
        • Деление на нуль и остаток с делителем нуля также относятся к неопределенному поведению.
        • Беззнаковое деление/остаток не имеют других особых случаев.
        • Деление со знаком может вызывать переполнение, например INT_MIN / -1 .
        • Остаток со знаком при отрицательных операндах может вызывать сложности, так как некоторые части являются однообразными, в то время как другие определяются реализацией.
        • Неопределенным поведением считается битовый сдвиг (< < и >>) на размер, который либо отрицателен, либо равен или больше битовой ширины.
        • Левый сдвиг беззнакового операнда (после продвижения/преобразования) считается определенным правильно и отклонений в поведении не вызывает.
        • Левый сдвиг операнда со знаком, содержащего неотрицательное значение, вследствие которого 1 бит переходит в знаковый бит, является неопределенным поведением.
        • Левый сдвиг отрицательного значения относится к неопределенному поведению.
        • Правый сдвиг неотрицательного значения (в типе операнда без знака или со знаком) считается определенным правильно и отклонений в поведении не вызывает.
        • Правый сдвиг отрицательного значения определяется реализацией.

        Счетчик цикла

        Выбор типа

        Предположим, что у нас есть массив, в котором нужно обработать каждый элемент последовательно. Длина массива хранится в переменной len типа T0 . Как нужно объявить переменную счетчика цикла i типа T1 ?

        • Самым простым решением будет использовать тот же тип, что и у переменной длины. Например:
        • Говоря обобщенно, переменная счетчика типа T1 будет работать верно, если диапазон T1 будет являться (не строго) надмножетсвом диапазона T0 . Например, если len имеет тип uint16_t , тогда отсчет с использованием signed long (не менее 32 бит) сработает.
        • Говоря же более конкретно, счетчик цикла должен просто покрывать всю фактическую длину. Например, если len типа int гарантированно будет иметь значение в диапазоне [3,50] (обусловленное логикой приложения), тогда допустимо отсчитывать цикл, используя char без знака или со знаком (в котором однозначно можно представить диапазон [0,127] ).
        • Нежелательно использовать переменную длины и переменную счетчика с разной знаковостью. В этом случае сравнение вызовет неявное сложное преобразование, сопровождаемое характерными для платформы проблемами. К примеру, не стоит писать такой код:

        Отсчет вниз

        Для циклов, ведущих отсчет вниз, более естественным будет использовать счетчик со знаком, потому что тогда можно написать:

        При этом для беззнакового счетчика код будет таким:

        Примечание: сравнение i >= 0 имеет смысл только, когда i является числом со знаком, но всегда будет давать true , если оно будет беззнаковым. Поэтому, когда это выражение встречается в беззнаковом контексте, значит, автор кода скорее всего допустил ошибку в логике.

        Заблуждения

        Все пункты приведенного ниже списка являются мифами. Не опирайтесь на эти ложные убеждения, если хотите писать корректный и портируемый код.

        Типы данных в C++

        В этом руководстве мы узнаем об основных типах данных, таких как int, float, char и т.д. в программировании на C++, с помощью примеров.

        Что такое типы данных в C++?

        Типа данных в C++ – это объявления переменных. Они определяют тип и размер данных, связанных с переменными. Например:

        Здесь age – переменная типа int, это означает, что переменная может хранить только целые числа размером 2 или 4 байта.

        Основные типы данных

        В таблице ниже показаны основные типы данных в C++, их значение и размеры (в байтах):

        Тип данных Значение Размер (в байтах)
        int Целое число 2 или 4
        float Плавающая точка 4
        double Двойная плавающая точка 8
        char символ 1
        wchar_t Широкий характер 2
        bool Булево 1
        void Пустой

        Теперь давайте обсудим эти фундаментальные типы данных более подробно.

        1. int

        • Ключевое слово int в С++ используется для обозначения целых чисел.
        • Его размер обычно составляет 4 байта. Это означает, что он может хранить значения от -2147483648 до 2147483647.
        • Например:

        2. float и double

        • float и double используются для хранения чисел с плавающей запятой (десятичных и экспонент).
        • Размер числа с плавающей запятой составляет 4 байта, а размер double – 8 байтов. Следовательно, точность double в два раза выше, чем у float. Чтобы узнать больше, посетите C ++ float и double.
        • Например,

        Как упоминалось выше, эти два типа данных также используются для экспонента. Например:

        3. char

        • Ключевое слово char используется для символов.
        • Его размер составляет 1 байт.
        • В C++ символы заключаются в одинарные кавычки ”.
        • Например:

        Примечание. В С++ целочисленное значение хранится в переменной типа char, а не в самом символе.

        4. wchar_t

        • Широкий символ wchar_t похож на тип данных char, за исключением того, что его размер составляет 2 байта вместо 1.
        • Он используется для представления символов, для использования которых требуется больше памяти, чем для одного символа.
        • Например:

        Обратите внимание на букву L перед кавычками.

        Примечание. В C++ 11 также представлены два других типа символов фиксированного размера – char16_t и char32_t.

        5. bool

        • Тип данных bool имеет одно из двух возможных значений: true или false.
        • Логические значения используются в условных операторах и циклах.
        • Например:

        6. void

        • Ключевое слово void указывает на отсутствие данных. Это означает «ничего» или «не имеет значения».
        • Мы будем использовать void, когда узнаем о функциях и указателях.

        Примечание. Мы не можем объявлять переменные типа void.

        Модификаторы типа

        Мы можем дополнительно изменить некоторые из основных типов данных с помощью модификаторов типов. В C++ есть 4 модификатора типа:

        • signed;
        • unsigned;
        • short;
        • long.

        Мы можем изменить следующие типы данных с помощью вышеуказанных модификаторов:

        • int;
        • double;
        • char.

        Список измененных типов данных

        Тип данных Размер (в байтах) Значение
        signed int 4 используется для целых чисел (эквивалентно int)
        unsigned int 4 может хранить только положительные целые числа
        short 2 используется для небольших целых чисел (от -32768 до 32767)
        long не менее 4 используется для больших целых чисел (эквивалент long int)
        unsigned long 4 используется для больших положительных целых чисел или 0 (эквивалент unsigned long int)
        long long 8 используется для очень больших целых чисел (эквивалент long long int)
        unsigned long long 8 используется для очень больших положительных целых чисел или 0 (эквивалент unsigned long long int)
        long double 12 используется для больших чисел с плавающей запятой
        signed char 1 используется для символов (гарантированный диапазон от -127 до 127)
        unsigned char 1 используется для символов (от 0 до 255)

        Посмотрим на несколько примеров.

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

        Типы данных, производные от основных типов данных, являются производными типами. Например: массивы, указатели, типы функций, структуры и т.д.

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

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