Тип int

Структуры

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

struct birthday
{
    char name20];
    int day;
    int month;
    int year;
};

Объявление структур в теле программы всегда должно начинаться с ключевого struct (необязательно в C++). Доступ к элементам структуры осуществляется с помощью оператора . или ->, если мы работаем с указателем на структуру. Структуры могут содержать указатели на самих себя, что позволяет реализовывать многие структуры данных, основанных на связных списках. Такая возможность может показаться противоречивой, однако все указатели занимают одинаковое число байт, поэтому размер этого поля не изменится от числа полей структуры.

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

Некоторые особенности структур:

  1. Адрес памяти первого поля структуры равен адресу самой структуры
  2. Структуры могут быть инициализированы или приведены к какому-либо значению, с помощью составных литералов
  3. Пользовательские функции могут возвращать структуру, хотя часто не очень эффективны во время выполнения. С 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
2
3
4
5
6
7
8
9
10

#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
2
3
4
5
6
7
8
9
10

#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

/*
* File   : main.c
* Author : zentut.com
* Purpose: display sizes of integer types
*/
 
#include <stdio.h>
 

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
Добавить комментарий

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