Тип int
Содержание:
Структуры
Структуры в Си позволяют хранить несколько полей и в одной переменной. В других языках могут называться записями или кортежами. Например, данная структура хранит в себе имя человека и дату рождения:
struct birthday { char name20]; int day; int month; int year; };
Объявление структур в теле программы всегда должно начинаться с ключевого struct (необязательно в C++). Доступ к элементам структуры осуществляется с помощью оператора . или ->, если мы работаем с указателем на структуру. Структуры могут содержать указатели на самих себя, что позволяет реализовывать многие структуры данных, основанных на связных списках. Такая возможность может показаться противоречивой, однако все указатели занимают одинаковое число байт, поэтому размер этого поля не изменится от числа полей структуры.
Структуры не всегда занимают число байт, равное сумме байт их элементов. Компилятор обычно выравнивает элементы в блоки по 4 байта. Также есть возможность ограничить число бит, отводимое на конкретное поле, для этого надо после имени поля через двоеточие указать размер поля в битах. Такая возможность позволяет создавать битовые поля.
Некоторые особенности структур:
- Адрес памяти первого поля структуры равен адресу самой структуры
- Структуры могут быть инициализированы или приведены к какому-либо значению, с помощью составных литералов
- Пользовательские функции могут возвращать структуру, хотя часто не очень эффективны во время выполнения. С C99, структура может оканчиваться массивом переменного размера.
Примеры переполнения
Рассмотрим переменную unsigned, которая состоит из 4-х бит. Любое из двоичных чисел, перечисленных в таблице выше, поместится внутри этой переменной.
«Но что произойдет, если мы попытаемся присвоить значение, которое занимает больше 4-х бит?». Правильно! Переполнение. Наша переменная будет хранить только 4 наименее значимых (те, что справа) бита, все остальные — потеряются.
Например, если мы попытаемся поместить число 21 в нашу 4-битную переменную:
Десятичная система | Двоичная система |
21 | 10101 |
Число 21 занимает 5 бит (10101). 4 бита справа (0101) поместятся в переменную, а крайний левый бит (1) просто потеряется. Т.е. наша переменная будет содержать 0101, что равно 101 (нуль спереди не считается), а это уже число 5, а не 21.
Примечание: О конвертации чисел из двоичной системы в десятичную и наоборот будет отдельный урок, где мы всё детально рассмотрим и обсудим.
Теперь рассмотрим пример в коде (тип short занимает 16 бит):
#include <iostream>
int main()
{
unsigned short x = 65535; // наибольшее значение, которое может хранить 16-битная unsigned переменная
std::cout << «x was: » << x << std::endl;
x = x + 1; // 65536 — это число больше максимально допустимого числа из диапазона допустимых значений. Следовательно, произойдёт переполнение, так как переменнная x не может хранить 17 бит
std::cout << «x is now: » << x << std::endl;
return 0;
}
1 |
#include <iostream> intmain() { unsignedshortx=65535;// наибольшее значение, которое может хранить 16-битная unsigned переменная std::cout<<«x was: «<<x<<std::endl; x=x+1;// 65536 — это число больше максимально допустимого числа из диапазона допустимых значений. Следовательно, произойдёт переполнение, так как переменнная x не может хранить 17 бит std::cout<<«x is now: «<<x<<std::endl; return; } |
Результат выполнения программы:
Что случилось? Произошло переполнение, так как мы попытались присвоить переменной значение больше, чем она способна в себе хранить.
Для тех, кто хочет знать больше: Число 65 535 в двоичной системе счисления представлено как 1111 1111 1111 1111. 65 535 — это наибольшее число, которое может хранить 2-байтовая (16 бит) целочисленная переменная без знака, так как это число использует все 16 бит. Когда мы добавляем 1, то получаем число 65 536. Число 65 536 представлено в двоичной системе как 1 0000 0000 0000 0000, и занимает 17 бит! Следовательно, самый главный бит (которым является 1) теряется, а все 16 бит справа — остаются. Комбинация 0000 0000 0000 0000 соответствует десятичному 0, что и является нашим результатом.
Аналогичным образом, мы получим переполнение, использовав число меньше минимального из диапазона допустимых значений:
#include <iostream>
int main()
{
unsigned short x = 0; // наименьшее значение, которое 2-байтовая unsigned переменная может хранить
std::cout << «x was: » << x << std::endl;
x = x — 1; // переполнение!
std::cout << «x is now: » << x << std::endl;
return 0;
}
1 |
#include <iostream> intmain() { unsignedshortx=;// наименьшее значение, которое 2-байтовая unsigned переменная может хранить std::cout<<«x was: «<<x<<std::endl; x=x-1;// переполнение! std::cout<<«x is now: «<<x<<std::endl; return; } |
Результат выполнения программы:
Переполнение приводит к потере информации, а это никогда не приветствуется. Если есть хоть малейшее подозрение или предположение, что значением переменной может быть число, которое находится вне диапазона допустимых значений используемого типа данных — используйте тип данных побольше!
Правило: Никогда не допускайте возникновения переполнения в ваших программах!
Целочисленные данные
Целочисленные данные могут быть представлены в знаковой и беззнаковой форме.Беззнаковые целые числа представляются в виде последовательности битов в диапазоне от 0 до 2n-1, где n-количество занимаемых битов.Знаковые целые числа представляются в диапазоне -2n-1…+2n-1-1. При этом старший бит данного отводится под знак числа (0 соответствует положительному числу, 1 – отрицательному).
Основные типы и размеры целочисленных данных:
Количество бит | Беззнаковый тип | Знаковый тип |
8 |
unsigned char 0…255 |
char -128…127 |
16 |
unsigned short 0…65535 |
short -32768…32767 |
32 | unsigned int | int |
64 | unsigned long int | long int |
Getting the sizes of integer types
To obtain the size of an integer type, or any type, you use the operator. The following program demonstrates how to use the operator to get the sizes of various integer types in your system.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* intmain() { printf(«sizeof(short) = %d bytes\n»,sizeof(short)); printf(«sizeof(int) = %d bytes\n»,sizeof(int)); printf(«sizeof(unsigned int) = %d bytes\n»,sizeof(unsignedint)); printf(«sizeof(long) = %d bytes\n»,sizeof(long)); return; } |
The following is the output in our system:
1 2 3 4 |
sizeof(short)=2bytes sizeof(int)=4bytes sizeof(unsignedint)=4bytes sizeof(long)=4bytes |
In this tutorial, we have introduced various C integer types and shown you how to use the operator to get the sizes of integer types in your system.
- Was this tutorial helpful ?
Ссылочные типы данных
Ссылочные типы данных не являются примитивными и их размер не фиксирован и может быть произвольным, кроме того они хранятся не на участке памяти переменной, а в совершенно другом месте памяти компьютера. Ссылочными типами, например, являются массивы. В объектно-ориентированных языках программирования – это экземпляры классов, коллекции и т.п.
При создании нового массива:
C#
int[] mass = new int;
1 | intmass=newint5; |
Или экземпляра класса:
C#
StreamWriter sw = new StreamWriter(«output.txt»);
1 | StreamWriter sw=newStreamWriter(«output.txt»); |
Память в компьютере для созданного объекта выделяется с помощью оператора new (C++, C#, Java), а в переменную объекта (в нашем случае это mass и sw) заносится лишь ссылка на участок памяти (адрес), в котором располагается созданный объект.
Передавая объект в качестве аргумента методу (или функции), в метод передаётся лишь копия адреса, но не копия объекта. Соответственно все изменения и манипуляции, производимые с объектом в вызванном методе, отразятся на объекте в вызывающем методе, потому что это один и тот же объект.
Вот в чём заключается отличие примитивных типов данных от ссылочных.
Поделиться в соц. сетях:
Классификация
Существуют различные классификации типов и правил их назначения.
По аналогии с математикой, типы данных делят на скалярные (примитивные) и нескалярные (агрегатные). Значение нескалярного типа (нескалярное значение) имеет множество видимых пользователю компонентов, а значение скалярного типа (скалярное значение) не имеет такового. Примерами нескалярного типа являются массивы, списки и т. д.; примеры скалярного типа — «целое», «логическое» и т. д.
Структурные (агрегатные) типы не следует отождествлять со структурами данных: одни структуры данных непосредственно воплощаются определёнными структурными типами, но другие строятся посредством их композиции, чаще всего рекурсивной. В последнем случае говорят о . Примером структур данных, которые почти всегда строятся посредством композиции объектов рекурсивного типа, являются бинарные деревья.
По другой классификации типы делятся на самостоятельные и зависимые. Важными разновидностями последних являются ссылочные типы, частным случаем которых, в свою очередь, являются указатели. Ссылки (в том числе и указатели) представляют собой несоставной зависимый тип, значения которого являются адресом в памяти ЭВМ другого значения. Например, в системе типов Си тип «указатель на целое без знака» записывается как «», в языке ML тип «ссылка на целое без знака» записывается как «».
Также типы делятся на мономорфные и полиморфные (см. переменная типа).
Primitive Built-in Types
C++ offers the programmer a rich assortment of built-in as well as user defined data types. Following table lists down seven basic C++ data types −
Type | Keyword |
---|---|
Boolean | bool |
Character | char |
Integer | int |
Floating point | float |
Double floating point | double |
Valueless | void |
Wide character | wchar_t |
Several of the basic types can be modified using one or more of these type modifiers −
- signed
- unsigned
- short
- long
The following table shows the variable type, how much memory it takes to store the value in memory, and what is maximum and minimum value which can be stored in such type of variables.
Type | Typical Bit Width | Typical Range |
---|---|---|
char | 1byte | -127 to 127 or 0 to 255 |
unsigned char | 1byte | 0 to 255 |
signed char | 1byte | -127 to 127 |
int | 4bytes | -2147483648 to 2147483647 |
unsigned int | 4bytes | 0 to 4294967295 |
signed int | 4bytes | -2147483648 to 2147483647 |
short int | 2bytes | -32768 to 32767 |
unsigned short int | 2bytes | 0 to 65,535 |
signed short int | 2bytes | -32768 to 32767 |
long int | 8bytes | -2,147,483,648 to 2,147,483,647 |
signed long int | 8bytes | same as long int |
unsigned long int | 8bytes | 0 to 4,294,967,295 |
long long int | 8bytes | -(2^63) to (2^63)-1 |
unsigned long long int | 8bytes | 0 to 18,446,744,073,709,551,615 |
float | 4bytes | |
double | 8bytes | |
long double | 12bytes | |
wchar_t | 2 or 4 bytes | 1 wide character |
The size of variables might be different from those shown in the above table, depending on the compiler and the computer you are using.
Following is the example, which will produce correct size of various data types on your computer.
#include <iostream> using namespace std; int main() { cout << "Size of char : " << sizeof(char) << endl; cout << "Size of int : " << sizeof(int) << endl; cout << "Size of short int : " << sizeof(short int) << endl; cout << "Size of long int : " << sizeof(long int) << endl; cout << "Size of float : " << sizeof(float) << endl; cout << "Size of double : " << sizeof(double) << endl; cout << "Size of wchar_t : " << sizeof(wchar_t) << endl; return 0; }
This example uses endl, which inserts a new-line character after every line and << operator is being used to pass multiple values out to the screen. We are also using sizeof() operator to get size of various data types.
When the above code is compiled and executed, it produces the following result which can vary from machine to machine −
Size of char : 1 Size of int : 4 Size of short int : 2 Size of long int : 4 Size of float : 4 Size of double : 8 Size of wchar_t : 4