Int c диапазон: С | Типы данных

Содержание

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



  • Чтение занимает 2 мин

В этой статье

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

  • 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 имеют размер четыре байта. Однако переносимый код не должен зависеть от размера, int так как языковой стандарт позволяет реализовать его в зависимости от реализации.

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

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

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

См. также раздел

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



Модификаторы типов | Программирование на C и C++

За исключением типа void, основные типы данных могут иметь различные модификаторы. Модификаторы используются для более точного управления ситуацией. Ниже приведен список модификаторов:
signed
unsigned
short

Модификаторы signed, unsigned, long и short могут применяться к целочисленным типам. К символам можно применять signed и unsigned, long может применяться к типу double. Таблица показывает все допустимые комбинации стандарта ANSI С для 16-битных типов данных вместе с размером типа в битах и границами применения в Borland С++.

Все допустимые комбинации базовых типов и модификаторов для 16-битных слов
Тип Длина в битах Диапазон
char 8 от-128 до 127
unsigned char 8 от 0 до 255
signed char 8 от-128 до 127
int 16 от-32768 до 32767
unsigned int 16 от 0 до 65535
signed int 16 от -32768 до 32767
short int 16 от -32768 до 32767
unsigned short int 16 от 0 до 65535
signed short int 16 от -32768 до 32767
long int 32 от -2147483648 до 2147483647
unsigned long int 32 от 0 до 4294967295
signed long int. 32 от -2147483648 до 2147483647
float 32 от 3.4е-38 до 3.4е+38
double 64 от 1.7е-308 до 1.7e+308
long double 80 от 3.4е-4932 до 1.1e+4932

Таблица  содержит информацию о 32-битных типах данных.

Таблица Все допустимые комбинации базовых типов и модификаторов дпя 32-битных слов
Тип Длина в битах Диапазон от-128 до 127
char 8 от 128 до 127
unsigned char 8 от 0 до 255
signed char 8 от -128 до 127
int 32 от -2147483648 до 2147483647
unsigned int 32 от 0 до 4294967295
signed int 32 от -2147483648 до 2147483647
short int 16 от -32768 до 32767
unsigned short int 16 от 0 до 65535
signed short int 16 от -32768 до 32767
long int 32 от -2147483648 до 2147483647
unsigned long int 32 от 0 до 4294967295
signed long int 32 от -2147483648 до 2147483647
float 32 от 3.4e-38 до 3.4е+38
double 64 от 1.7е-308 до 1.7е+308
long double 80 от 3.4е-4932 до 1.1e+4932

Использование signed для целочисленных типов является избыточным (но допустимым), поскольку объявление целочисленных типов по умолчанию предполагает знаковое число.

Различие между знаковыми и беззнаковыми целочисленными типами заключается в способе интерпретации старшего бита. Если используется знаковый тип, то компилятор генерирует код, предполагающий, что старший бит используется как знак числа. Если знаковый бит равен 0, то число положительное, а если 1 — отрицательное. Ниже приведены простые примеры:

Следует предупредить, что фактически все компьютеры используют дополнительную арифметику, что приводит к представлению —127 в виде, слегка отличном от вышеприведенного примера. Тем не менее, использование знакового бита является однотипным. У отрицательного числа в дополнительном виде все биты инвертированы, и к числу добавляется 1. Например, —127 в дополнительном виде выглядит следующим образом:

1111111110000001

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

01111111 11111111

Если старший бит установлен в 1, то число будет интерпретироваться как —1. Тем не менее, если объявить его как unsigned int, то, если старший бит установлен, число будет содержать 65535.
 

C int диапазон значений

Компиляторы C++ Microsoft 32-bit и 64-bit распознают типы в таблице далее в этой статье. The Microsoft C++ 32-bit and 64-bit compilers recognize the types in the table later in this article.

int ( unsigned int ) int ( unsigned int )

__int8 ( unsigned __int8 ) __int8 ( unsigned __int8 )

__int16 ( unsigned __int16 ) __int16 ( unsigned __int16 )

__int32 ( unsigned __int32 ) __int32 ( unsigned __int32 )

__int64 ( unsigned __int64 ) __int64 ( unsigned __int64 )

short ( unsigned short ) short ( unsigned short )

long ( unsigned long ) long ( unsigned long )

long long ( unsigned long long ) long long ( unsigned long long )

Если имя начинается с двух символов подчеркивания ( __ ), тип данных является нестандартным. If its name begins with two underscores ( __ ), a data type is non-standard.

Диапазоны, представленные в следующей таблице, включают указанные значения. The ranges that are specified in the following table are inclusive-inclusive.

Имя типа Type NameБайт BytesДругие имена Other NamesДиапазон значений Range of Values
int int4 4signed signedОт -2 147 483 648 до 2 147 483 647 -2,147,483,648 to 2,147,483,647
unsigned int unsigned int4 4unsigned unsignedОт 0 до 4 294 967 295 0 to 4,294,967,295
__int8 __int81 1char charОт -128 до 127 -128 to 127
неподписанный __int8 unsigned __int81 1unsigned char unsigned charОт 0 до 255 0 to 255
__int16 __int162 2Short, короткое целое, короткое целое число со знаком short, short int, signed short intОт -32 768 до 32 767 -32,768 to 32,767
неподписанный __int16 unsigned __int162 2короткое число без знака, короткое целое без знака unsigned short, unsigned short intОт 0 до 65 535 0 to 65,535
__int32 __int324 4со знаком, целое число со знаком, целое число signed, signed int, intОт -2 147 483 648 до 2 147 483 647 -2,147,483,648 to 2,147,483,647
неподписанный __int32 unsigned __int324 4Неподписанное целое число без знака unsigned, unsigned intОт 0 до 4 294 967 295 0 to 4,294,967,295
__int64 __int648 8длинный длинный знак Long long long, signed long longОт -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
unsigned __int64 unsigned __int648 8длинное целое без знака unsigned long longОт 0 до 18 446 744 073 709 551 615 0 to 18,446,744,073,709,551,615
bool bool1 1Нет nonefalse или true false or true
char char1 1Нет noneот-128 до 127 по умолчанию -128 to 127 by default

При компиляции при помощи /J — от 0 до 255 0 to 255 when compiled by using /J

знак со знаком signed char1 1Нет noneОт -128 до 127 -128 to 127unsigned char unsigned char1 1Нет noneОт 0 до 255 0 to 255short short2 2короткое целое, короткое целое со знаком short int, signed short intОт -32 768 до 32 767 -32,768 to 32,767unsigned short unsigned short2 2unsigned short int unsigned short intОт 0 до 65 535 0 to 65,535long long4 4long int, длинное целое число со знаком long int, signed long intОт -2 147 483 648 до 2 147 483 647 -2,147,483,648 to 2,147,483,647unsigned long unsigned long4 4unsigned long int unsigned long intОт 0 до 4 294 967 295 0 to 4,294,967,295long long long long8 8нет (но эквивалентно __int64) none (but equivalent to __int64)От -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807длинное целое без знака unsigned long long8 8нет (но эквивалентно неподписанному __int64) none (but equivalent to unsigned __int64)От 0 до 18 446 744 073 709 551 615 0 to 18,446,744,073,709,551,615enum enumВозможны разные варианты variesНет nonefloat float4 4Нет none3,4E +/- 38 (7 знаков) 3.4E +/- 38 (7 digits)double double8 8Нет none1,7E +/- 308 (15 знаков) 1.7E +/- 308 (15 digits)long double long doubleто же, что и Double same as doubleНет noneТо же, что и Double Same as doublewchar_t wchar_t2 2__wchar_t __wchar_tОт 0 до 65 535 0 to 65,535

В зависимости от того, как он используется, переменная __wchar_t обозначает либо тип расширенных символов, либо многобайтовый символ. Depending on how it’s used, a variable of __wchar_t designates either a wide-character type or multibyte-character type. Чтобы указать константу расширенного символьного типа, перед символьной или строковой константой следует использовать префикс L . Use the L prefix before a character or string constant to designate the wide-character-type constant.

знаки со знаком и без знака — это модификаторы, которые можно использовать с любым целочисленным типом, кроме bool. signed and unsigned are modifiers that you can use with any integral type except bool. Обратите внимание , что char, знак charи неподписанный символ — это три различных типа для таких механизмов, как перегрузка и шаблоны. Note that char, signed char, and unsigned char are three distinct types for the purposes of mechanisms like overloading and templates.

Целочисленные и неподписанные типы int имеют размер четыре байта. The int and unsigned int types have a size of four bytes. Однако переносимый код не должен зависеть от размера int , так как языковой стандарт позволяет реализовать его в зависимости от реализации. However, portable code should not depend on the size of int because the language standard allows this to be implementation-specific.

C и C++ в Visual Studio также поддерживают целочисленные типы с указанием размера. C/C++ in Visual Studio also supports sized integer types. Дополнительные сведения см. в разделах __int8, __int16, __int32, __int64 и Пределы целых чисел. For more information, see __int8, __int16, __int32, __int64 and Integer Limits.

Дополнительные сведения об ограничениях размеров каждого типа см. в разделе Встроенные типы. For more information about the restrictions of the sizes of each type, see Built-in types.

Диапазон перечисляемых типов зависит от контекста языка и указанных флажков компилятора. The range of enumerated types varies depending on the language context and specified compiler flags. Дополнительные сведения см. в статьях Объявления перечислений C и Объявления перечислений C++. For more information, see C Enumeration Declarations and Enumerations.

Все о коде и не только

  • Получить ссылку
  • Facebook
  • Twitter
  • Pinterest
  • Электронная почта
  • Другие приложения

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

Составные типы

Символьный тип

Данные типа char в памяти компьютера всегда занимают 1 байт. Это связа­но с тем, что обычно под величину символьного типа отводят столько памяти, сколько необходимо для хранения любого из 256 символов клавиатуры.
Сим­вольный тип может быть со знаком или без знака.
В величинах со знаком signed char можно хранить значения в диапазоне от -128 до 127. Соответствен­но значения переменных типа unsigned char могут находиться в диапазоне от 0 до 255.

Последние новости со всего мира Получите расширение Bing + MSN

Опубликовано: Июнь 2016

Самая актуальная документация по Visual Studio 2017: Документация по Visual Studio 2017.

Компиляторы Visual C++ (32-разрядные и 64-разрядные) поддерживают типы, указанные в приведенной ниже таблице.

long long ( unsigned«long«long )

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

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

Имя типаБайтыДругие именаДиапазон значений
int4signedОт -2 147 483 648 до 2 147 483 647
unsigned int4без знакаОт 0 до 4 294 967 295
__int81charОт -128 до 127
unsigned __int81unsigned charОт 0 до 255
__int162короткое, короткое целочисленное, короткое целочисленное со знакомОт -32 768 до 32 767
unsigned __int162короткое без знака, короткое целочисленное без знакаОт 0 до 65 535
__int324со знаком, целочисленное со знаком, целочисленноеОт -2 147 483 648 до 2 147 483 647
unsigned __int324без знака, целочисленное без знакаОт 0 до 4 294 967 295
__int648длинное длинное, со знаком длинное длинноеОт -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
unsigned __int648без знака длинное длинноеОт 0 до 18 446 744 073 709 551 615
bool1Нетfalse или true
char1НетПо умолчанию — от -128 до 127

При компиляции при помощи /J — от 0 до 255

signed char1НетОт -128 до 127unsigned char1НетОт 0 до 255short2короткое целочисленное, короткое целочисленное со знакомОт -32 768 до 32 767unsigned short2короткое целочисленное число без знакаОт 0 до 65 535long4длинное целочисленное, длинное целочисленное со знакомОт -2 147 483 648 до 2 147 483 647unsigned long4длинное целочисленное число без знакаОт 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 615enumВозможны разные вариантыНетСм. раздел Заметки ниже в этой статье.плавающее4Нет3,4E +/- 38 (7 знаков)double8Нет1,7E +/- 308 (15 знаков)длинное двойноеТо же, что и для двойногоНетТо же, что и для двойного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 и Пределы целых чисел.

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

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

c — Что означает «-1» в диапазоне значений для unsigned int и sign int?

Я изучаю C и имею тупой вопрос относительно «-1» в диапазоне значений для unsigned int и sign int. Я не могу найти объяснение этому нигде.

Параграф ниже объясняет диапазон данных. Однако это не объясняет «-1». Что означает «-1»? Это -1, потому что он пропускает 0, а 0 не имеет значения?

В 32-разрядных целых числах целое число без знака имеет диапазон от 0 до 2 ^ 32 -1 = от 0 до 4 294 967 295 или около 4 миллиардов. 31, что составляет от –2 147 483 648 до 2 147 483 647 или около -2 млрд до +2 млрд. Диапазон такой же, но он сдвинут на числовой линии.

25

biscuit

29 Авг 2019 в 08:21

5 ответов

Лучший ответ

п

3

000
001
010
011
100
101
110
111

п

  • Он может представлять целые числа от 0 до 2 n -1 включительно
    (потому что (2 n -1) — (0) + 1 = 2 п разные значения).

    Например,

    000   0
    001   1
    010   2
    011   3
    100   4
    101   5
    110   6
    111   7
    
  • Он может представлять целые числа от -2 n-1 до 2 n-1 -1 включительно
    (потому что (2 n-1 ) > -1) — (-2 n-1 ) + 1 = 2 n различных значений).

    Например,

    100  -4
    101  -3
    110  -2
    111  -1
    000   0
    001   1
    010   2
    011   3
    

[ 1 ]


  1. На своем дополнении есть два способа записи нуля (0000. ..0000 2 и 1000 … 0000 2 ), поэтому диапазон составляет всего от -2 n-1 -1 до 2 п — 1 -1 . Я думаю, что все современные машины являются дополнением до двух.

23

ikegami
24 Фев 2020 в 13:47

Для целого типа без знака значение -1 равно вне диапазона и не может быть представлено в переменной этого типа. Если вы попытаетесь присвоить -1 unsigned int, конверсия произойдет в соответствии с правилами стандарта C.

Преобразование значения со знаком в целочисленный тип без знака указано в разделе 6.3.1.3p2 документа стандарт C:

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

60) Правила описывают арифметику математического значения, а не значения данного типа выражения

Предполагая, как в вашем примере, что unsigned int имеет диапазон значений от 0 до 4 294 967 295, значение -1 преобразуется путем сложения -1 + 4 294 967 296 = 4 294 967 295. Обратите внимание, что это преобразование происходит независимо от того, как отрицательные числа представлены в данной системе. То же самое для комплимента двоих, комплимента своих или знака и величины.

Обратите внимание, что это означает, что представление преобразованного значения не должно совпадать с представлением -1.

Используя 4-битный тип в качестве примера, преобразование значения -1 в тип без знака приводит к значению 15. Представление этих чисел выглядит следующим образом:

                sign-and magnitude    ones' complement   two's complement
  -1   (signed)               1001                1110               1111
  15 (unsigned)               1111                1111               1111

Хотя в случае дополнения до двух результат преобразования остается тем же представлением, в других двух случаях он изменяется. Для дополнения представление -1 такое же, как для 14, а для знака и величины представление -1 такое же, как для 9.

Таким образом, то, что другие ответы описали относительно дополнения к двум, скорее всего, как эти реализации делают это (то есть переосмысливают представление -1 как значение без знака), однако с точки зрения языка C как абстрактной машины то, что я описал, является единственным правильный способ выполнения этого преобразования.

3

dbush
29 Авг 2019 в 18:53

В дополнение к превосходному объяснению @ Yunnosch о числах без знака, почти все современные компьютеры используют «дополнение двух» для представления двоичных чисел со знаком. В дополнение к двум наиболее значимый бит используется в качестве «знакового бита», а биты являются дополнением к абсолютному значению числа +1. Так, для примера с 3 битами, в то время как диапазон значений без знака равен от 0 до 7, диапазон для подписанных значений от -4 до 3:

100 : -4
101 : -3
110 : -2
111 : -1
000 :  0
001 :  1
010 :  2
011 :  3

Обратите внимание, что для чисел со знаком диапазон отрицательных чисел на единицу больше, чем диапазон положительных чисел. Это потому, что в теории чисел 0 не является ни положительным, ни отрицательным, в двоичном представлении 0 должен быть либо отрицательным, либо положительным. Поскольку он сбрасывает наиболее значимый бит, 0 является частью области положительных чисел, поэтому остается доступным одно менее положительное число.

5

daShier
29 Авг 2019 в 06:08

Рассмотрим значения, которые вы можете получить с 2 битами:

00 : 0
01 : 1
10 : 2
11 : 3

Их 4, 2 в степени 2. 2-1
или 2 2 -1

Добавьте немного, и вы получите вдвое больше, добавив

100 : 4
101 : 5
110 : 6
111 : 7

Всего 8, но наибольшее 7.

Таким образом, «-1» потому что всегда первое из 2 n используется для 0,
2-е используется для 1, 3-е используется для 2.
В конце (2 n ) -й один недоступен для 2 n , он уже используется для 2 n -1.

47

Yunnosch
29 Авг 2019 в 06:30

Где вы нашли этот неверный абзац? Похоже, что это дополнение к 2, но -1 находится не в том месте.

Для реализаций C, использующих целые числа со знаком или дополнением или знаком / величиной, диапазон симметричен относительно нуля (с 2-битными комбинациями, которые оба представляют 0, поэтому положительный диапазон и отрицательный диапазон имеют одинаковый размер).n.

Если только установить бит знака, мы получим наиболее отрицательное число : -INT_MIN переполнение со знаком (неопределенное поведение), поскольку оно не может быть представлено как {{X1 } } ; это требует более широкого целого числа. Или с упаковкой, -INT_MIN = INT_MIN. Это «аномалия комплемента 2». https://en.wikipedia.org/wiki/Two%27s_complement#Most_negative_number

Вы можете избежать расширения, если выполняете операцию с абсолютным значением: например,
unsigned abs = i >= 0 ? i : -(unsigned)i;

(Преобразование отрицательного значения в unsigned в C имеет четко определенное поведение уменьшения по модулю до тех пор, пока оно не окажется в представимом диапазоне. В C это не зависит от кодировки со знаком-целым числом; важно значение value . Так что (uint8_t)-1 всегда 255. Для дополнения 2 он просто копирует битовый шаблон. Для знака / величины или дополнения реализация C должна была бы выполнить некоторую математику для приведения от подписи к подписи. Обратите внимание, что я сделал это до отрицания, что означает 0 - i с обычным беззнаковым переносом.)

2

Peter Cordes
30 Авг 2019 в 00:09

Основы — SwiftBook

Swift — новый язык программирования для разработки приложений под iOS, macOS, watchOS и tvOS. Несмотря на это, многие части Swift могут быть вам знакомы из вашего опыта разработки на C и Objective-C.

Swift предоставляет свои собственные версии фундаментальных типов C и Objective-C, включая Int для целых чисел, Double и Float для значений с плавающей точкой, Bool для булевых значений, String для текста. Swift также предоставляет мощные версии трех основных типов коллекций, Array, Set и Dictionary, как описано в разделе Типы коллекций.

Подобно C, Swift использует переменные для хранения и обращения к значениям по уникальному имени. Swift также широко использует переменные, значения которых не могут быть изменены. Они известны как константы, и являются гораздо более мощными, чем константы в C. Константы используются в Swift повсеместно, чтобы сделать код безопаснее и чище в случаях, когда вы работаете со значениями, которые не должны меняться.

В дополнение к знакомым типам, Swift включает расширенные типы, которых нет в Objective-C. К ним относятся кортежи, которые позволяют создавать и передавать группы значений. Кортежи могут возвращать несколько значений из функции как одно целое значение.

Swift также включает опциональные типы, которые позволяют работать с отсутствующими значениями. Опциональные значения говорят либо «здесь есть значение, и оно равно х», либо «здесь нет значения вообще». Опциональные типы подобны использованию nil с указателями в Objective-C, но они работают со всеми типами, не только с классами. Опциональные значения безопаснее и выразительнее чем nil указатели в Objective-C, и находятся в сердце многих наиболее мощных особенностей Swift.

Swift — язык типобезопасный, что означает, что Swift помогает вам понять, с какими типами значений ваш код может работать. Если кусок вашего кода ожидает String, безопасность типов не даст вам передать ему Int по ошибке. Кроме того, безопасность типов не позволит вам случайно передать опциональный String куску кода, который ожидает неопциональный String. Безопасность типов позволяет вам улавливать и исправлять ошибки как можно раньше в процессе разработки.

Константы и переменные связывают имя (например, maximumNumberOfLoginAttempts или welcomeMessage) со значением определенного типа (например, число 10 или строка «Hello»). Значение константы не может быть изменено после его установки, тогда как переменной может быть установлено другое значение в будущем.

Объявление констант и переменных

Константы и переменные должны быть объявлены, перед тем как их использовать. Константы объявляются с помощью ключевого слова let, а переменные с помощью var. Вот пример того, как константы и переменные могут быть использованы для отслеживания количества попыток входа, которые совершил пользователь:

let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0

Этот код можно прочесть как:

«Объяви новую константу с именем maximumNumberOfLoginAttempts, и задай ей значение 10. Потом, объяви новую переменную с именем currentLoginAttempt, и задай ей начальное значение 0.»

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

Вы можете объявить несколько констант или несколько переменных на одной строке, разделяя их запятыми:

var x = 0.0, y = 0.0, z = 0.0
Заметка

Если хранимое значение в вашем коде не будет меняться, всегда объявляйте его как константу, используя ключевое слово let. Используйте переменные только для хранения значений, которые должны будут меняться.

Аннотация типов

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

Этот пример добавляет обозначение типа для переменной с именем welcomeMessage, чтобы обозначить, что переменная может хранить String:

var welcomeMessage: String

Двоеточие в объявлении значит «…типа…», поэтому код выше может быть прочитан как:

«Объяви переменную с именем welcomeMessage, тип которой будет String»

Фраза «тип которой будет String» означает «может хранить любое String значение». Представьте, что словосочетание «тип которой будет такой-то» означает — значение, которое будет храниться.

Теперь переменной welcomeMessage можно присвоить любое текстовое значение, без каких либо ошибок:

welcomeMessage = "Hello"

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

var red, green, blue: Double
Заметка

Редко когда вам понадобится обозначать тип на практике. Когда вы даете начальное значение константе или переменной на момент объявления, Swift всегда может вывести тип, который будет использовать в константе или переменной. Это описано в Строгая типизация и Вывод типов. В примере welcomeMessage выше, не было присвоения начального значения, так что тип переменной welcomeMessage указывается с помощью обозначения типа вместо того, чтобы вывести из начального значения.

Название констант и переменных

Вы можете использовать почти любые символы для названий констант и переменных, включая Unicode-символы:

let π = 3.14159
let 你好 = "你好世界"
let ?? = "dogcow"

Имена констант и переменных не могут содержать пробелы, математические символы, стрелки, приватные (или невалидные) кодовые точки Unicode, а так же символы отрисовки линий или прямоугольников. Так же имена не могут начинаться с цифр, хотя цифры могут быть включены в имя в любом другом месте. Если вы объявили константу или переменную определенного типа, то вы не можете объявить ее заново с тем же именем или заставить хранить внутри себя значение другого типа. Также вы не можете изменить константу на переменную, а переменную на константу.

Заметка

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

Вы можете изменить значение переменной на другое значение совместимого типа. В примере ниже значение friendlyWelcome изменено с “Hello!” на “Bonjour!”:

var friendlyWelcome = “Hello!”
friendlyWelcome = “Bonjour!”
// теперь friendlyWelcome имеет значение “Bonjour!”

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

let languageName = "Swift"
languageName = "Swift++"
// Это ошибка компилляции: languageName cannot be changed (значение languageName не может быть изменено).

Печать констант и переменных

Вы можете напечатать текущее значение константы или переменной при помощи функции print(_:separator:terminator:):

print(friendlyWelcome)
// Выведет "Bonjour!"

Функция print(_:separator:terminator:) является глобальной, которая выводит одно или более значений в подходящем виде. В Xcode, например, функция print(_:separator:terminator:) выводит значения в консоль. Параметры separator и terminator имеют дефолтные значения, так что при использовании функции их можно просто пропустить. По умолчанию функция заканчивает вывод символом переноса строки. Чтобы вывести в консоль значения без переноса на новую строку, вам нужно указать пустую строку в параметре terminator, например, print(someValue, terminator: «»). Для получения дополнительной информации по дефолтным значениям параметров обратитесь в раздел «Значения по умолчанию для параметров».

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

print("Текущее значение friendlyWelcome равно \(friendlyWelcome)")
// Выведет "Текущее значение friendlyWelcome равно Bonjour!"
Заметка

Все опции, которые вы можете использовать в интерполяции строки вы сможете найти в разделе «Интерполяция строк».

Используйте комментарии, чтобы добавить неисполняемый текст в коде, как примечание или напоминание самому себе. Комментарии игнорируются компилятором Swift во время компиляции кода.

Комментарии в Swift очень похожи на комментарии в C. Однострочные комментарии начинаются с двух слешей (//):

// это комментарий

Вы также можете написать многострочные комментарии, которые начинаются со слеша и звездочки (/*) и заканчиваются звездочкой, за которой следует слеш (*/):

/* это тоже комментарий,
но написанный на двух строках */

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

/* это начало первого многострочного комментария
/* это второго, вложенного многострочного комментария */
это конец первого многострочного комментария */

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

В отличие от многих других языков, Swift не требует писать точку с запятой (;) после каждого выражения в коде, хотя вы можете делать это, если хотите. Однако точки с запятой требуются, если вы хотите написать несколько отдельных выражений на одной строке:

let cat = "?"; print(cat)
// Выведет "?"

Integer (целое число) — это число, не содержащее дробной части, например, как 42 и -23. Целые числа могут быть либо знаковыми (положительными, ноль или отрицательными) либо беззнаковыми (положительными или ноль).

Swift предусматривает знаковые и беззнаковые целые числа в 8, 16, 32 и 64 битном форматах. Эти целые числа придерживаются соглашения об именах, аналогичных именам в C, в том, что 8-разрядное беззнаковое целое число имеет тип Uint8, а 32-разрядное целое число имеет тип Int32. Как и все типы в Swift, эти типы целых чисел пишутся с заглавной буквой.

Границы целых чисел

Вы можете получить доступ к минимальному и максимальному значению каждого типа целого числа с помощью его свойств min и max:

let minValue = UInt8.min // minValue равен 0, а его тип UInt8
let maxValue = UInt8.max // maxValue равен 255, а его тип UInt8

Тип значения этих свойств соответствует размеру числа (в примере выше этот тип UInt8) и поэтому может быть использован в выражениях наряду с другими значениями того же типа.

Int

В большинстве случаев вам не нужно будет указывать конкретный размер целого числа для использования в коде. В Swift есть дополнительный тип целого числа — Int, который имеет тот же размер что и разрядность системы:

  • На 32-битной платформе, Int того же размера что и Int32
  • На 64-битной платформе, Int того же размера что и Int64

Если вам не нужно работать с конкретным размером целого числа, всегда используйте в своем коде Int для целых чисел. Это придает коду логичность и совместимость. Даже на 32-битных платформах, Int может хранить любое значение в пределах -2 147 483 648 и 2 147 483 647, а этого достаточно для многих диапазонов целых чисел.

UInt

Swift также предусматривает беззнаковый тип целого числа — UInt, который имеет тот же размер что и разрядность системы:

  • На 32-битной платформе, UInt того же размера что и UInt32
  • На 64-битной платформе, UInt того же размера что и UInt64
Заметка

Используйте UInt, только когда вам действительно нужен тип беззнакового целого с размером таким же, как разрядность системы. Если это не так, использовать Int предпочтительнее, даже когда известно, что значения будут неотрицательными. Постоянное использование Int для целых чисел способствует совместимости кода, позволяет избежать преобразования между разными типами чисел, и соответствует выводу типа целого числа, как описано в Строгая типизация и Вывод Типов.

Число с плавающей точкой — это число с дробной частью, например как 3.14159, 0.1, и -273.15.

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

  • Double — представляет собой 64-битное число с плавающей точкой. Используйте его когда число с плавающей точкой должно быть очень большим или чрезвычайно точным
  • Float — представляет собой 32-битное число с плавающей точкой. Используйте его, когда значение не нуждается в 64-битной точности.
Заметка

Double имеет точность минимум 15 десятичных цифр, в то время как точность Float может быть всего лишь 6 десятичных цифр. Соответствующий тип числа с плавающей точкой используется в зависимости от характера и диапазона значений, c которыми вы должны работать в коде. В случаях, где возможно использование обоих типов, предпочтительным считается Double.

Swift — язык со строгой типизацией. Язык со строгой типизацией призывает вас иметь четкое представление о типах значений, с которыми может работать ваш код. Если часть вашего кода ожидает String, вы не сможете передать ему Int по ошибке.

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

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

Благодаря выводу типов, Swift требует гораздо меньше объявления типов, чем языки, такие как C или Objective-C. Константам и переменным все же нужно присваивать тип, но большая часть работы с указанием типов будет сделана за вас.

Вывод типов особенно полезен, когда вы объявляете константу или переменную с начальным значением. Часто это делается путем присвоения литерального значения (или литерала) к константам или переменным в момент объявления​​. (Литеральное значение — значение, которое появляется непосредственно в исходном коде, например как 42 и 3,14159 в примерах ниже.)

Например, если вы присваиваете литеральное значение 42 к новой константе не сказав какого она типа, Swift делает вывод, что вы хотите чтобы константа была Int, потому что вы присвоили ей значение, которое похоже на целое число:

let meaningOfLife = 42
// meaningOfLife выводится как тип Int

Точно так же, если вы не указали тип для литерала с плавающей точкой, Swift делает вывод, что вы хотите создать Double:

let pi = 3.14159
// pi выводится как тип Double

Swift всегда выбирает Double (вместо Float), когда выводит тип чисел с плавающей точкой.

Если объединить целые литералы и литералы с плавающей точкой в одном выражении, в этом случае тип будет выводиться как Double:

let anotherPi = 3 + 0.14159
// anotherPi тоже выводится как тип Double

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

Числовые литералы могут быть написаны как:

  • Десятичное число, без префикса
  • Двоичное число, с префиксом 0b
  • Восьмеричное число, с префиксом 0o
  • Шестнадцатеричное число, с префиксом 0x

Все эти литералы целого числа имеют десятичное значение 17:

let decimalInteger = 17
let binaryInteger = 0b10001 // 17 в двоичной нотации
let octalInteger = 0o21 // 17 в восмеричной нотации
let hexadecimalInteger = 0x11 // 17 в шестнадцатеричной нотации

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

Для десятичных чисел с показателем степени ехр, базовое число умножается на 10exp:

  • 1.25e2 означает 1.25 × 102, или 125.0.
  • 1.25e-2 означает 1.25 × 10-2, или 0.0125.

Для шестнадцатеричных чисел с показателем степени ехр, базовое число умножается на 2exp:

  • 0xFp2 означает 15 × 22, или 60.0.
  • 0xFp-2 означает 15 × 2-2, или 3.75.

Все эти числа с плавающей точкой имеют десятичное значение 12.1875:

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

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

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

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

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

Преобразования целых чисел

Диапазон значений, который может храниться в целочисленных константах и переменных, различен для каждого числового типа. Int8 константы и переменные могут хранить значения между -128 и 127, тогда как UInt8 константы и переменные могут хранить числа между 0 и 255. Если число не подходит для переменной или константы с определенным размером, выводится ошибка во время компиляции:

let cannotBeNegative: UInt8 = -1
// UInt8 не может хранить отрицательные значения, поэтому эта строка выведет ошибку
let tooBig: Int8 = Int8.max + 1
// Int8 не может хранить число больше своего максимального значения,
// так что это тоже выведет ошибку

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

Чтобы преобразовать один числовой тип в другой, необходимо создать новое число желаемого типа из существующего значения. Ниже, в примере, константа twoThousand имеет тип UInt16, тогда как константа one — UInt8. Сложить их напрямую не получится, потому что они разного типа. Вместо этого, в примере вызывается функция UInt16(one) для создания нового числа UInt16 из значения константы one:

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

Теперь, из-за того, что обе части сложения имеют тип UInt16 — операция сложения допустима. Для конечной константы (twoThousandAndOne) выведен тип UInt16, потому что это сложение двух UInt16 значений.

НазваниеТипа(начальноеЗначение) — стандартный способ вызвать инициализатор типов Swift и передать начальное значение. Честно говоря, у UInt16 есть инициализатор, который принимает UInt8 значение, и, таким образом, этот инициализатор используется, чтобы создать новый UInt16 из существующего UInt8. Здесь вы не можете передать любой тип, однако это должен быть тип, для которого у UInt16 есть инициализатор. Расширение существующих типов с помощью создания инициализаторов, которые принимают новые типы (включая объявление вашего типа) рассматривается в главе Расширения.

Преобразования целых чисел и чисел с плавающей точкой

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

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi равно 3.14159, и для него выведен тип Double

Здесь, значение константы three используется для создания нового значения типа Double, так что обе части сложения имеют один тип. Без этого преобразования сложение не будет проходить. Обратное преобразование числа с плавающей точкой в целое число тоже должно происходить явно. Так что тип целого числа может быть инициализирован с помощью Double и Float значений:

let integerPi = Int(pi)
// integerPi равен 3, и для него выведен тип Int

Числа с плавающей точкой всегда урезаются, когда вы используете инициализацию целого числа через этот способ. Это означает, что 4.75 будет 4, а -3.9 будет -3.

Заметка

Правила объединения числовых констант и переменных отличается от правил числовых литералов. Литеральное значение 3 может напрямую сложиться с литеральным значением 0.14159, потому что числовые литералы сами по себе не имеют явного типа. Их тип выводится только в момент оценки значения компилятором.

Псевдонимы типов задают альтернативное имя для существующего типа. Можно задать псевдоним типа с помощью ключевого слова typealias.

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

typealias AudioSample = UInt16

После того как вы один раз задали псевдоним типа, вы можете использовать псевдоним везде, где вы хотели бы его использовать

var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound теперь 0

Здесь AudioSample определен как псевдоним для UInt16. Поскольку это псевдоним, вызов AudioSample.min фактически вызовет UInt16.min, что показывает начальное значение 0 для переменной maxAmplitudeFound.

В Swift есть простой логический тип Bool. Этот тип называют логическим, потому что он может быть только true или false. Swift предусматривает две логические константы, true и false соответственно:

let orangesAreOrange = true
let turnipsAreDelicious = false

Типы для orangesAreOrange и turnipsAreDelicious были выведены как Bool, исходя из того факта, что мы им присвоили логические литералы. Так же как с Int и Double в предыдущих главах, вам не нужно указывать константы или переменные как Bool, если при создании вы присвоили им значения true или false. Вывод типов помогает сделать код Swift кратким и читабельным тогда, когда вы создаете константы или переменные со значениями которые точно известны.

Логические значения очень полезны когда вы работаете с условными операторами, такими как оператор if:

if turnipsAreDelicious {
 print("Mmm, tasty turnips!")
} else {
 print("Eww, turnips are horrible.")
}
// Выведет "Eww, turnips are horrible."

Условные операторы, такие как оператор if детально рассматриваются в главе Управление потоком.

Строгая типизация Swift препятствует замене значения Bool на не логическое значение. Следующий пример выведет ошибку компиляции:

let i = 1
if i {
 // этот пример не скомпилируется, и выдаст ошибку компиляции
}

Тем не менее, альтернативный пример ниже правильный:

let i = 1
if i == 1 {
 // этот пример выполнится успешно
}

Результат сравнения i == 1 имеет тип Bool, и поэтому этот второй пример совершает проверку типов. Такие сравнения как i == 1 обсуждаются в главе Базовые операторы.

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

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

В данном примере (404, «Not Found») это кортеж, который описывает код HTTP статуса. Код HTTP статуса — особое значение, возвращаемое веб-сервером каждый раз, когда вы запрашиваете веб-страницу. Код статуса 404 Not Found возвращается, когда вы запрашиваете страницу, которая не существует.

let http404Error = (404, "Not Found")
// http404Error имеет тип (Int, String), и равен (404, "Not Found")

Чтобы передать код статуса, кортеж (404, «Not Found») группирует вместе два отдельных значения Int и String: число и понятное человеку описание. Это может быть описано как «кортеж типа (Int, String)».

Вы можете создать кортеж с любой расстановкой типов, и они могут содержать сколько угодно нужных вам типов. Ничто вам не мешает иметь кортеж типа (Int, Int, Int), или типа (String, Bool), или же с любой другой расстановкой типов по вашему желанию.

Вы можете разложить содержимое кортежа на отдельные константы и переменные, к которым можно получить доступ привычным способом:

let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// Выведет "The status code is 404"
print("The status message is \(statusMessage)")
// Выведет "The status message is Not Found"

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

let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// Выведет "The status code is 404"

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

print("The status code is \(http404Error.0)")
// Выведет "The status code is 404"
print("The status message is \(http404Error.1)")
// Выведет "The status message is Not Found"

Вы можете давать имена отдельным элементам кортежа во время объявления:

let http200Status = (statusCode: 200, description: "OK")

Когда вы присвоили имя элементу кортежа, вы можете обратиться к нему по имени:

print("The status code is \(http200Status.statusCode)")
// Выведет "The status code is 200"
print("The status message is \(http200Status.description)")
// Выведет "The status message is OK"

Кортежи особенно полезны в качестве возвращаемых значений функций. Функция, которая пытается получить веб-страницу, может вернуть кортеж типа (Int, String), чтобы описать успех или неудачу в поиске страницы. Возвращая кортеж с двумя отдельными значениями разного типа, функция дает более полезную информацию о ее результате, чем, если бы, возвращала единственное значение одного типа, возвращаемое функцией. Для более подробной информации смотрите главу Функции, возвращающие несколько значений.

Заметка

Кортежи полезны для временной группировки связанных значений. Они не подходят для создания сложных структур данных. Если ваша структура данных, вероятно, будет выходить за рамки временной структуры, то такие вещи лучше проектируйте с помощью классов или структур, вместо кортежей. Для получения дополнительной информации смотрите главу Классы и структуры.

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

Заметка

В C или Objective-C нет понятия опционалов. Ближайшее понятие в Objective-C это возможность вернуть nil из метода, который в противном случае вернул бы объект. В этом случае nil обозначает «отсутствие допустимого объекта». Тем не менее, это работает только для объектов, и не работает для структур, простых типов C, или значений перечисления. Для этих типов, методы Objective-C, как правило, возвращают специальное значение (например, NSNotFound), чтобы указать отсутствие значения. Этот подход предполагает, что разработчик, который вызвал метод, знает, что есть это специальное значение и что его нужно учитывать. Опционалы Swift позволяют указать отсутствие значения для абсолютно любого типа, без необходимости использования специальных констант.

Приведем пример, который покажет, как опционалы могут справиться с отсутствием значения. У типа Int в Swift есть инициализатор, который пытается преобразовать значение String в значение типа Int. Тем не менее, не каждая строка может быть преобразована в целое число. Строка «123» может быть преобразована в числовое значение 123, но строка «hello, world» не имеет очевидного числового значения для преобразования.

В приведенном ниже примере используется метод Int() для попытки преобразовать String в Int:

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// для convertedNumber выведен тип "Int?", или "опциональный Int"

Поскольку метод Int() может иметь недопустимый аргумент, он возвращает опциональный Int, вместо Int. Опциональный Int записывается как Int?, а не Int. Знак вопроса означает, что содержащееся в ней значение является опциональным, что означает, что он может содержать некое Int значение, или он может вообще не содержать никакого значения. (Он не может содержать ничего другого, например, Bool значение или значение String. Он либо Int, либо вообще ничто)

nil

Мы можем установить опциональную переменную в состояние отсутствия значения, путем присвоения ему специального значения nil

var serverResponseCode: Int? = 404
// serverResponseCode содержит реальное Int значение 404
serverResponseCode = nil
// serverResponseCode теперь не содержит значения
Заметка

nil не может быть использован с не опциональными константами и переменными. Если значение константы или переменной при определенных условиях в коде должно когда-нибудь отсутствовать, всегда объявляйте их как опциональное значение соответствующего типа.

Если объявить опциональную переменную без присвоения значения по умолчанию, то переменная автоматически установится в nil для вас:

var surveyAnswer: String?
// surveyAnswer автоматически установится в nil
Заметка

nil в Swift не то же самое что nil в Objective-C. В Objective-C nil является указателем на несуществующий объект. В Swift nil не является указателем, а является отсутствием значения определенного типа. Устанавливаться в nil могут опционалы любого типа, а не только типы объектов.

Инструкция If и Принудительное извлечение

Вы можете использовать инструкцию if, сравнивая опционал с nil, чтобы проверить, содержит ли опционал значение. Это сравнение можно сделать с помощью оператора «равенства» (==) или оператора «неравенства» (!=).

Если опционал имеет значение, он будет рассматриваться как «неравным» nil:

if convertedNumber != nil {
    print("convertedNumber contains some integer value.")
}
// Выведет "convertedNumber contains some integer value."

Если вы уверены, что опционал содержит значение, вы можете получить доступ к его значению, добавив восклицательный знак (!) в конце имени опционала. Восклицательный знак фактически говорит: «Я знаю точно, что этот опционал содержит значение, пожалуйста, используй его». Это выражение известно как Принудительное извлечение значения опционала:

if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}
// Выведет "convertedNumber has an integer value of 123."

Более подробную информацию об инструкции if можно получить в главе Управление потоком.

Заметка

Попытка использовать ! к несуществующему опциональному значению вызовет runtime ошибку. Всегда будьте уверены в том, что опционал содержит не-nil значение, перед тем как использовать ! чтобы принудительно извлечь это значение.

Привязка опционалов

Можно использовать Привязку опционалов, чтобы выяснить содержит ли опционал значение, и если да, то сделать это значение доступным в качестве временной константы или переменной. Привязка опционалов может использоваться с инструкциями if и while, для проверки значения внутри опционала, и извлечения этого значения в константу или переменную, в рамках одного действия. Инструкции if и while более подробно представлены в главе Управление потоком.

Привязку опционалов для инструкции if можно писать как показано ниже:

  1. if let constantName = someOptional {
  2.     statements
  3. }

Мы можем переписать пример possibleNumber сверху, используя привязку опционалов, а не принудительное извлечение:

if let actualNumber = Int(possibleNumber) {
    print("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
    print("\(possibleNumber) could not be converted to an integer")
}
// Выведет "123" has an integer value of 123

Это может быть прочитано как:

«Если опциональный Int возвращаемый Int(possibleNumber) содержит значение, установи в новую константу с названием actualNumber значение, содержащееся в опционале.»

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

Вы можете использовать и константы и переменные для привязки опционалов. Если вы хотели использовать значение actualNumber внутри первого ветвления инструкции if, вы могли бы написать if var actualNumber вместо этого, и значение, содержащееся в опционале, будет использоваться как переменная, а не константа.

Вы можете включать столько опциональных привязок и логических условий в единственную инструкцию if, сколько вам требуется, разделяя их запятыми. Если какое-то значение в опциональной привязке равно nil, или любое логическое условие вычисляется как false, то все условия выражения будет считаться false. Следующие инструкции if эквиваленты:

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}
// Выведет "4 < 42 < 100"
 
if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}
// Выведет "4 < 42 < 100"
Заметка

Константы и переменные, созданные через опциональную привязку в инструкции if, будут доступны только в теле инструкции if. В противоположность этому, константы и переменные, созданные через инструкцию guard, доступны в строках кода, следующих за инструкцией guard, что отражено в разделе Ранний Выход.

Неявно извлеченные опционалы

Как описано выше, опционалы показывают, что константам или переменным разрешено не иметь «никакого значения». Опционалы можно проверить с помощью инструкции if, чтобы увидеть существует ли значение, и при условии, если оно существует, можно извлечь его с помощью привязки опционалов для доступа к опциональному значению.

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

Эти виды опционалов называются неявно извлеченные опционалы. Их можно писать, используя восклицательный знак (String!), вместо вопросительного знака (String?), после типа, который вы хотите сделать опциональным.

Неявно извлеченные опционалы полезны, когда известно, что значение опционала существует непосредственно после первого объявления опционала, и точно будет существовать после этого. Неявно извлечённые опционалы в основном используются во время инициализации класса, как описано в разделе «Бесхозные ссылки и неявно извлеченные опциональные свойства».

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

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // необходим восклицательный знак

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // восклицательный знак не нужен

Вы можете считать неявно извлеченные опционалы обычными опционалами дающими разрешение на принудительное извлечение, если это требуется. Когда вы используете неявно извлеченный опционал, то Swift сначала пробует использовать его в качестве обычного опционального значения, если так его использовать не получается, то уже пробует принудительно извлечь значение. В коде выше опциональное значение assumedString является принудительно извлеченным прежде, чем будет записано в implicitString, так как implicitString имеет явный неопциональный тип String. В коде ниже optionalString не имеет явного типа, так что является обычным функционалом.

let optionalString = assumedString
// Тип optionalString является "String?" и assumedString не является принудительно извлеченным значением.

Если вы попытаетесь получить доступ к неявно извлеченному опционалу когда он не содержит значения — вы получите runtime ошибку. Результат будет абсолютно тот же, если бы вы разместили восклицательный знак после нормального опционала, который не содержит значения.

Вы можете проверить не является ли неявно извлеченный функционал nil точно так же как вы проверяете обычный функционал:

if assumedString != nil {
    print(assumedString!)
}
// Выведет "An implicitly unwrapped optional string."

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

if let definiteString = assumedString {
  print(definiteString)
}
// Выведет "An implicitly unwrapped optional string."
Заметка

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

Вы используете обработку ошибок в ответ на появление условий возникновения ошибок во время выполнения программы.

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

Когда функция обнаруживает условие ошибки, она выдает сообщение об ошибке. Тот, кто вызывает функцию, может затем поймать ошибку и среагировать соответствующим образом.

func canThrowAnError() throws {
// эта функция может сгенерировать ошибку
}

Функция сообщает о возможности генерации ошибки, включив ключевое слово throws в объявление. Когда вы вызываете функцию, которая может выбросить ошибку, вы добавляете ключевое слово try в выражение. Swift автоматически передает ошибки из их текущей области, пока они не будут обработаны условием catch.

do {
  try canThrowAnError()
  // ошибка не была сгенерирована
} catch {
  // ошибка сгенерирована
}

Выражение do создает область, содержащую объект, которая позволяет ошибкам быть переданными в одно или несколько условий catch.

Вот пример того, как обработка ошибок может быть использована в ответ на различные условия возникновения ошибок:

func makeASandwich() throws {
    // ...
}
 
do {
    try makeASandwich()
    eatASandwich()
} catch SandwichError.outOfCleanDishes {
    washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

В этом примере, функция makeASandwich() генерирует ошибку, если нет чистых тарелок или если отсутствуют какие-либо ингредиенты. Так как makeASandwich() может выдавать ошибку, то вызов функции заворачивают в выражении try. При заворачивании вызова функции в выражение do, генерация каких-либо ошибок, будет передаваться на предусмотренные условия catch.

Если ошибка не генерируется, то вызывается функция eatASandwich(). Если ошибка все таки генерируется, и она соответствует SandwichError.outOfCleanDishes, то вызывается функция washDishes(). Если генерируется ошибка, и она соответствует SandwichError.missingIngredients , то функция buyGroceries(_:) вызывается с соответствующим значением [String], захваченным шаблоном catch.

Генерация, вылавливание и передача ошибок рассмотрены более подробно в главе Обработка ошибок.

Утверждения и предусловия являются проверками во время исполнения. Вы используете их для того, чтобы убедиться, что какое-либо условие уже выполнено, прежде чем начнется исполнение последующего кода. Если булево значение в утверждении или в предусловии равно true, то выполнение кода просто продолжается далее, но если значение равно false, то текущее состояние исполнения программы некорректно и выполнение кода останавливается и ваше приложение завершает работу.

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

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

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

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

Отладка с помощью утверждений

Утверждения записываются как функция стандартной библиотеки Swift assert(_:_:file:line:). Вы передаете в эту функцию выражение, которые оценивается как true или false и сообщение, которое должно отображаться, если результат условия будет false. Например:

let age = -3
assert(age >= 0, "Возраст человека не может быть меньше нуля")
// это приведет к вызову утверждения, потому что age >= 0, а указанное значение < 0.

В этом примере, выполнение кода продолжится, только если age >= 0 вычислится в true, что может случиться, если значение age не отрицательное. Если значение age отрицательное, как в коде выше, тогда age >= 0 вычислится как false, и запустится утверждение, завершив за собой приложение.

Сообщение утверждения можно пропускать по желанию, как в следующем примере:

assert(age >= 0)

Если код уже проверяет условие, то вы используете функцию assertionFailure(_:file:line:) для индикации того, что утверждение не выполнилось. Например:

if age > 10 {
    print("Ты можешь покататься на американских горках и чертовом колесе.")
} else if age > 0 {
    print("Ты можешь покататься на чертовом колесе.")
} else {
    assertionFailure("Возраст человека не может быть отрицательным.")
}

Обеспечение предусловиями

Используйте предусловие везде, где условие потенциально может получить значение false, но для дальнейшего исполнения кода оно определенно должно равняться true. Например, используйте предусловие для проверки того, что значение сабскрипта не вышло за границы диапазона или для проверки того, что в функцию было передано корректное значение.

Для использования предусловий вызовите функцию precondition(_:_:file:line:). Вы передаете этой функции выражение, которое вычисляется как true или false и сообщение, которое должно отобразиться, если условие будет иметь значение как false. Например:

 // В реализации сабскрипта...
precondition(index > 0, "Индекс должен быть больше нуля.")

Вы так же можете вызвать функцию preconditionFailure(_:_:file:line:) для индикации, что отказ работы уже произошел, например, если сработал дефолтный кейс инструкции switch, когда известно, что все валидные значения должны быть обработаны любым кейсом, кроме дефолтного.

Заметка

Если вы компилируете в режиме -0unchecked, то предусловия не проверяются. Компилятор предполагает, что предусловия всегда получают значения true, и он оптимизирует ваш код соответствующим образом. Однако, функция fatalError(_:file:line:) всегда останавливает исполнение, несмотря на настройки оптимизации.

Вы можете использовать функцию fatalError (_:file:line:) во время прототипирования или ранней разработки для создания заглушек для функциональности, которая еще не реализована, написав fatalError («Unimplemented») в качестве реализации заглушки. Поскольку фатальные ошибки никогда не оптимизируются, в отличие от утверждений или предусловий, вы можете быть уверены, что выполнение кода всегда прекратится, если оно встречает реализацию заглушки.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Digital Chip

Все данные в языке Си имеют свой тип. Переменные определенных типов занимают в памяти какое-то место, разное в зависимости от типа. В Си нет четкого закрепления количества памяти за определенными типами. Это отдано на реализацию конкретного компилятора под конкретную платформу. Например, переменная типа int в одном компиляторе может занимать в памяти 16 бит, в другом — 32 бита, в третьем — 8 бит. Все определяет конкретный компилятор. Правда, все стремятся к универсализации, и в основном в большинстве компиляторов тип int, например, занимает 2 байта, а тип char — один.

Я в последнее время немного затупил, не мог вспомнить, сколько байт занимает тип double в AVR-GCC. Обычно при программировании контроллеров работаешь с целочисленными типами, типа int и char, а к типам с плавающей точкой прибегаешь не часто, в связи с их ресурсоемкостью.

Поэтому, на будущее, оставлю себе здесь памятку с указанием размеров занимаемой памяти типами данных для компилятора AVR-GCC и диапазон изменения переменных этого типа.

Типы данных в языке Си для компилятора AVR-GCC

ТипРазмер в
байтах (битах)
Интервал изменения
char1 (8)-128 .. 127
unsigned char1 (8)0 .. 255
signed char1 (8)-128 .. 127
int2 (16)-32768 .. 32767
unsigned int2 (16)0 .. 65535
signed int2 (16)-32768 .. 32767
short int2 (16)-32768 .. 32767
unsigned short int2 (16)0 .. 65535
signed short int2 (16)-32768 .. 32767
long int4 (32)-2147483648 .. 2147483647
unsigned long int4 (32)0 .. 4294967295
signed long int4 (32)-2147483648 .. 2147483647
float4 (32)3.4Е-38 .. 3.4Е+38
double4 (32)3.4Е-38 .. 3.4Е+38
long double10 (80)3.4Е-4932 .. 3.4Е+4932

[stextbox id=»warning» caption=»Обратите внимание»]Реализация типа double в AVR-GCC отступает от стандарта. По стандарту double занимает 64 бита. В AVR-GCC переменная этого типа занимает 32 бита, и соответственно, она эквивалентна переменной с типом float![/stextbox]

В дополнение к этому, в библиотеках AVR-GCC введено несколько производных от стандартных типов. Они описаны в файле stdint.h. Сделано это, наверно, для улучшения наглядности и уменьшения текста программ (ускорения их написания :)). Вот табличка соответствия:

Производные типы от стандартных в языке Си для компилятора AVR-GCC

Производный типСтандартный тип
int8_tsigned char
uint8_tunsigned char
int16_tsigned int
uint16_tunsigned int
int32_tsigned long int
uint32_tunsigned long int
int64_tsigned long long int
uint64_tunsigned long long int

Тип Void

В языке Си есть еще один тип — тип void. Void используется для указания, что функция не возвращает ничего в качестве результата, или не принимает на вход никаких параметров. Этот тип не применяется для объявления переменных, соответственно он не занимает места в памяти.

4. Целочисленный (целый) тип данных (тип int)

Лекция № Типы
данных.

Содержание
лекции.

  1. Понятие типа
    данных

  2. Классификация
    типа данных.

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

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

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

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

внутреннее
представление данных в памяти компьютера;

объем памяти,
выделяемый под данные;

множество
(диапазон) значений, которые могут
принимать величины этого типа;

операции и функции,
которые можно применять к данным этого
типа.

Исходя из данных
характеристик, необходимо определять
тип каждой величины, используемой в
программе для представления объектов.
Обязательное описание типа позволяет
компилятору производить проверку
допустимости различных конструкций
программы. От выбора типа величины
зависит последовательность машинных
команд, построенная компилятором.

2.
Классификация типов данных в С++

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

Объектно-ориентированные
языки программирования позволяют
определять типы класса.

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

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

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

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

Типы класса.
Экземпляры этих типов называются
объектами.

Рис. 1.1. Типы
данных в языке С++

            1. Спецификаторы
              типов данных

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

short (короткий) длина

long (длинный)

signed (знаковый) знак
(модификатор)

unsigned (беззнаковый)

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

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

Границы диапазона
целых чисел, которые можно хранить в
переменных типа int, зависят от конкретного
компьютера, компилятора и операционной
системы (от реализации). Для 16-разрядного
процессора под него отводится 2 байта,
для 32-разрядного – 4 байта.

Для внутреннего
представления знаковых целых чисел
характерно определение знака по старшему
биту (0 – для положительных, 1 – для
отрицательных). Поэтому число 0 во
внутреннем представлении относится к
положительным значениям. Следовательно,
наблюдается асимметрия границ целых
промежутков.

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

От количества
отводимой под объект памяти зависит
множество допустимых значений, которые
может принимать объект:

short int – занимает
2 байта, следовательно, имеет диапазон
от –32 768 до +32 767;

int – занимает 4
байта, следовательно, имеет диапазон
от –2 147 483 648 до +2 147 483 647;

long int – занимает
4 байта, следовательно, имеет диапазон
от –2 147 483 648 до +2 147 483 647;

long long int – занимает
8 байтов, следовательно, имеет диапазон
от –9 223 372 036 854 775 808 до +9 223 372 036 854 775 807.

Модификаторы
signed и unsigned также влияют на множество
допустимых значений, которые может
принимать объект:

unsigned short int –
занимает 2 байта, следовательно, имеет
диапазон от 0 до 65 535;

unsigned int – занимает
4 байта, следовательно, имеет диапазон
от 0 до 4 294 967 295;

unsigned long int –
занимает 4 байта, следовательно, имеет
диапазон от 0 до 4 294 967 295;

unsigned long long int –
занимает 8 байтов, следовательно, имеет
диапазон от 0 до 18 446 744 073 709 551 615.

Например:

unsigned int b;

signed int a;

int c;

unsigned d;

signed f;

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

Нельзя пользоваться
десятичной точкой. Значения 26 и 26.0
одинаковы, но 26.0 не является значением
типа int.

Нельзя пользоваться
запятыми в качестве разделителей тысяч.
Например, число 23,897 следует записывать
как 23897.

Целые значения
не должны начинаться с незначащего
нуля. Он применяется для обозначения
восьмеричных или шестнадцатеричных
чисел, так что компилятор будет
рассматривать значение 011 как число 9 в
восьмеричной системе счисления.

На практике
рекомендуется использовать основной
целый тип, то есть тип int. Данные основного
целого типа практически всегда
обрабатываются быстрее, чем данные
других целых типов. Короткий тип short
подойдет для хранения больших массивов
чисел с целью экономии памяти при
условии, что значения элементов не
выходят за предельные границы для этих
типов. Длинные типы необходимы в ситуации,
когда не достаточно типа int.

Размер C «int» 2 байта или 4 байта?

Целочисленная переменная в C занимает 2 или 4 байта?

Это зависит от платформы, которую вы используете, а также от того, как настроен ваш компилятор. Единственный авторитетный ответ — использовать оператор sizeof , чтобы узнать, насколько велико целое число в вашей конкретной ситуации.


От каких факторов это зависит?

Лучше всего рассмотреть диапазон , а не размер .На практике оба варианта будут отличаться, хотя, как мы увидим, гораздо безопаснее выбирать типы переменных по диапазону, а не по размеру. Также важно отметить, что стандарт побуждает нас рассмотреть вопрос о выборе наших целочисленных типов на основе диапазона , а не размера , но пока давайте проигнорируем стандартную практику и дадим нашему любопытству изучить размером байтов и CHAR_BIT , и целочисленное представление … давайте закопаем кроличью нору и посмотрим сами…


размером байтов и CHAR_BIT

Следующее утверждение, взятое из стандарта C (связанное с выше), описывает это словами, которые, я не думаю, можно улучшить.

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

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

Давайте подведем итоги:

  • sizeof => размер в байтах, а
  • CHAR_BIT => количество бит в байте

Таким образом, в зависимости от вашей системы, sizeof (unsigned int) может быть любое значение больше нуля (не только 2 или 4), как если бы CHAR_BIT было 16, тогда одиночным (шестнадцатибитным) байт имеет достаточно битов для представления шестнадцатиразрядного целого числа, описанного стандартами (цитируется ниже).Это не обязательно полезная информация, не так ли? Давайте углубимся …


Целочисленное представление

Стандарт C определяет минимальную точность / диапазон для всех стандартных целочисленных типов (а также CHAR_BIT , fwiw). Из этого мы можем вывести минимум для того, сколько битов требуется для хранения значения , но мы также можем просто выбрать наши переменные на основе диапазонов . Тем не менее, большая часть деталей, необходимых для этого ответа, находится здесь.Например, для стандартного unsigned int требуется (как минимум) шестнадцать бит памяти:

  UINT_MAX 65535 // 2¹⁶ - 1
  

Таким образом, мы видим, что unsigned int требует ( не менее ) 16 бит , где вы получаете два байта (при условии, что CHAR_BIT равно 8) … и позже, когда этот предел увеличился до 2³² - 1 , вместо этого люди указывали 4 байта.Это объясняет наблюдаемые вами явления:

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

.

Вы используете древний учебник и компилятор, который обучает вас непереносимому C; автор, написавший ваш учебник, может даже не знать о CHAR_BIT . Вам следует обновить свой учебник (и компилятор) до и постараться помнить, что I.T. — это постоянно развивающаяся область, и вам нужно оставаться на впереди , чтобы конкурировать … Впрочем, об этом хватит; давайте посмотрим, какие еще непереносимые секреты хранятся в этих базовых целочисленных байтах

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

Знаковые биты … В приведенном выше примере я процитировал UINT_MAX как верхний предел для unsigned int , потому что это тривиальный пример извлечения значения 16 из комментария.Для типов со знаком, чтобы различать положительные и отрицательные значения (это знак), нам также необходимо включить бит знака.

  INT_MIN -32768 // - (2¹⁵)
INT_MAX +32767 // 2¹⁵ - 1
  

Биты заполнения … Хотя нечасто можно встретить компьютеры, у которых есть биты заполнения в целых числах, стандарт C допускает это; некоторые машины (то есть эта) реализуют более крупные целочисленные типы путем объединения двух меньших (знаковых) целочисленных значений вместе… и когда вы комбинируете целые числа со знаком, вы получаете потерянный знаковый бит. Этот потерянный бит считается заполнением в C. Другие примеры битов заполнения могут включать в себя биты четности и биты ловушки.


Как видите, стандарт, кажется, поощряет рассмотрение диапазонов, таких как INT_MIN .. INT_MAX и других минимальных / максимальных значений из стандарта при выборе целочисленных типов, а не рекомендует полагаться на размеры, поскольку есть другие тонкие факторы вероятно, будут забыты, такие как CHAR_BIT и биты заполнения, которые могут повлиять на значение sizeof (int) (т.е. распространенное заблуждение двухбайтовых и четырехбайтовых целых чисел ( игнорирует эти детали).

Типы данных языка C | Studytonight

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

Язык C поддерживает 2 разных типа данных:

  1. Первичные типы данных :

    Это основные типы данных в C, а именно целые числа ( int ), с плавающей запятой ( float ), символьные ( char ) и void .

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

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

Тип данных определяет тип данных, которые будет содержать переменная. Если
переменная x объявлена ​​как int . это означает, что x может содержать только целые значения.
Каждая переменная, которая используется в программе, должна быть объявлена ​​как
тип данных это.


Целочисленный тип

Целые числа используются для хранения целых чисел.

Размер и диапазон целочисленного типа на 16-битной машине:

9023 9023 короткий int

9023 908 или короткое int со знаком

до 2,122847

Тип Размер (байты) Диапазон
int или подписанный int 2-32,768 до 32767
беззнаковый int 2 1 от -128 до 127
беззнаковое короткое int 1 от 0 до 255
long int или длинное со знаком int 4-2,147,483,648 unsigned long int 4 от 0 до 4,294,967,295

Тип с плавающей запятой

Плавающие типы используются для хранения действительных чисел.

Размер и диапазон целочисленного типа на 16-битной машине

Тип Размер (байты) Диапазон
Float 4 3.4E-38 до 3.4E + 38
двойной 8E от 1.7E-308 до 1.7E-308 308
длинный двойной 10 3.4E-4932 до 1.1E + 4932

Тип символа

Типы символов используются для хранения значений символов.

Размер и диапазон целочисленного типа на 16-битной машине

пустота тип

void type означает отсутствие значения. Обычно это используется для указания типа функций, которые ничего не возвращают. Мы познакомимся с этим типом данных, когда начнем изучать более сложные темы на языке C, такие как функции, указатели и т. Д.n) — 1. Где n — количество бит в обоих случаях.

Программа / исходный код

Вот исходный код программы C для печати диапазона. Программа на C успешно скомпилирована и запускается в системе Linux. Вывод программы также показан ниже.

  1.  / * 
  2.  * Программа на C для печати диапазона 
  3.  * / 
  4.  #include  
  5.  #define SIZE (x) sizeof (x) * 8 
  6.  
  7.  void signed_one (int); 
  8.  void unsigned_one (int); 
  9.  
  10.  void main () 
  11.  {
  12.  printf ("\ n диапазон int"); 
  13.  signed_one (РАЗМЕР (int)); 
  14.  printf ("\ n диапазон беззнаковых целых чисел"); 
  15.  unsigned_one (РАЗМЕР (целое число без знака)); 
  16.  printf ("\ n диапазон символов"); 
  17.  signed_one (РАЗМЕР (символ)); 
  18.  printf ("\ n диапазон беззнаковых символов"); 
  19.  unsigned_one (РАЗМЕР (символ без знака)); 
  20.  printf ("\ n диапазон коротких"); 
  21.  signed_one (РАЗМЕР (короткий)); 
  22.  printf ("\ n диапазон беззнаковых коротких"); 
  23.  unsigned_one (РАЗМЕР (беззнаковое короткое)); 
  24.  
  25. } 
  26.  / * ВОЗВРАЩАЕТ ПОДПИСАННЫЙ ДИАПАЗОН * / 
  27.  void signed_one (int count) 
  28.  {
  29.  int min, max, pro; 
  30.  pro = 1; 
  31.  в то время как (count! = 1) 
  32.  {
  33.  pro = pro << 1; 
  34.  кол-; 
  35. } 
  36.  min = ~ pro; 
  37.  мин = мин + 1; 
  38.  max = pro - 1; 
  39.  printf ("\ n% d до% d", min, max); 
  40. } 
  41.  / * ВОЗВРАЩАЕТ НЕПОДПИСАННЫЙ ДИАПАЗОН * / 
  42.  void unsigned_one (int count) 
  43.  {
  44.  unsigned int min, max, pro = 1; 
  45.  
  46.  в то время как (count! = 0) 
  47.  {
  48.  pro = pro << 1; 
  49.  кол-; 
  50. } 
  51.  мин = 0; 
  52.  max = pro - 1; 
  53.  printf ("\ n% u to% u", min, max); 
  54. } 

Описание программы

1.Преобразуйте количество байтов в биты, умножив байты на 8.
2. Используйте две функции, а именно signed_one () и unsigned_one (), для вычисления диапазона типов данных со знаком и без знака соответственно.
3. Значение, полученное на шаге 1, отправляется как параметр в обе функции. В обеих функциях он получен по счетчику переменных.
4. Установите для переменной pro значение 1 в обеих функциях.
5. В функции signed_one (), использующей цикл while с условием (count! = 1), сдвиньте переменную pro влево на 1 позицию и последовательно уменьшите количество переменных на 1.
6. Когда цикл завершится, присвойте дополнение pro переменной min и увеличьте min на 1. Уменьшите значение переменной pro и присвойте ее переменной max. Напечатайте min и max в качестве вывода.
7. В функции unsigned_one (), использующей цикл while с условием (count! = 0), сдвиньте переменную pro влево на 1 позицию и последовательно уменьшите количество переменных на 1.
8. Когда цикл завершится, присвойте ноль переменной min. Уменьшите значение переменной pro и присвойте ее переменной max.Напечатайте min и max в качестве вывода.

Случаи тестирования

диапазон int
От -2147483648 до 2147483647
диапазон беззнаковых целых
0 на 4294967295
диапазон знаков
От -128 до 127
диапазон беззнаковых символов
От 0 до 255
диапазон коротких
От -32768 до 32767
диапазон беззнаковых коротких
0 до 65535 

Sanfoundry Global Education & Learning Series - 1000 программ C.

Вот список лучших справочников по программированию, структурам данных и алгоритмам на C

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

примитивных типов данных (Руководства по Java ™> Изучение языка Java> Основы языка)

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

Это сообщает вашей программе, что поле с именем "шестерня" существует, содержит числовые данные и имеет начальное значение "1".Тип данных переменной определяет значения, которые она может содержать, а также операции, которые могут выполняться с ней. В дополнение к int , язык программирования Java поддерживает семь других примитивных типов данных . Примитивный тип предопределен языком и назван зарезервированным ключевым словом. Примитивные значения не разделяют состояние с другими примитивными значениями. Язык программирования Java поддерживает следующие восемь примитивных типов данных:

  • байт : Тип данных байт представляет собой 8-битовое целое число с дополнением до двух со знаком.Он имеет минимальное значение -128 и максимальное значение 127 (включительно). Тип данных байт может быть полезен для экономии памяти в больших объемах.
    массивы, где действительно важна экономия памяти. Их также можно использовать вместо int , где их пределы помогают прояснить ваш код; тот факт, что диапазон переменной ограничен, может служить формой документации.

  • short : Тип данных short - это 16-разрядное целое число со знаком в дополнительном коде.Он имеет минимальное значение -32 768 и максимальное значение 32 767 (включительно). Как и в случае с байтом , применяются те же правила: вы можете использовать короткий для экономии памяти в больших массивах в ситуациях, когда экономия памяти действительно имеет значение.

  • int : по умолчанию тип данных int представляет собой 32-битное знаковое целое число с дополнением до двух, которое имеет минимальное значение -2 31 и максимальное значение 2 31 -1. В Java SE 8 и более поздних версиях вы можете использовать тип данных int для представления 32-битного целого числа без знака, минимальное значение которого равно 0, а максимальное - 2 32 -1.Используйте класс Integer, чтобы использовать тип данных int как целое число без знака. См. Раздел «Числовые классы» для получения дополнительной информации. Статические методы, такие как compareUnsigned , diverUnsigned и т. Д., Были добавлены в
    Integer Класс для поддержки арифметических операций с целыми числами без знака.

  • long : Тип данных long представляет собой 64-битное целое число с дополнением до двух. Длинное число со знаком имеет минимальное значение -2 63 и максимальное значение 2 63 -1.В Java SE 8 и более поздних версиях вы можете использовать тип данных long для представления беззнакового 64-битного типа long, который имеет минимальное значение 0 и максимальное значение 2 64 -1. Используйте этот тип данных, если вам нужен более широкий диапазон значений, чем предоставленный int . В
    Long Класс также содержит такие методы, как compareUnsigned , diverUnsigned и т. Д. Для поддержки арифметических операций для значений unsigned long.

  • с плавающей запятой : Тип данных с плавающей запятой представляет собой 32-битное число с плавающей запятой одинарной точности IEEE 754.Диапазон его значений выходит за рамки данного обсуждения, но указан в
    Раздел «Типы, форматы и значения с плавающей запятой» Спецификации языка Java. Как и в случае с рекомендациями для байта и короткого , используйте с плавающей запятой (вместо double ), если вам нужно сохранить память в больших массивах чисел с плавающей запятой. Этот тип данных никогда не следует использовать для точных значений, таких как валюта. Для этого вам нужно будет использовать
    java.math.BigDecimal вместо этого.Numbers and Strings охватывает BigDecimal и другие полезные классы, предоставляемые платформой Java.

  • double : тип данных double представляет собой 64-битную плавающую точку IEEE 754 с двойной точностью. Диапазон его значений выходит за рамки данного обсуждения, но указан в
    Раздел «Типы, форматы и значения с плавающей запятой» Спецификации языка Java. Для десятичных значений этот тип данных обычно выбирается по умолчанию. Как упоминалось выше, этот тип данных никогда не следует использовать для точных значений, таких как валюта.

  • boolean : Тип данных boolean имеет только два возможных значения: true и false . Используйте этот тип данных для простых флагов, которые отслеживают истинные / ложные условия. Этот тип данных представляет один бит информации, но его «размер» не совсем точно определен.

  • char : Тип данных char - это один 16-битный символ Unicode. Он имеет минимальное значение '\ u0000' (или 0) и максимальное значение '\ uffff' (или 65 535 включительно).

В дополнение к восьми примитивным типам данных, перечисленным выше, язык программирования Java также обеспечивает специальную поддержку символьных строк через
java.lang.String класс. Заключение строки символов в двойные кавычки автоматически создаст новый объект String ; например, String s = "это строка"; . String Объекты являются неизменяемыми , что означает, что после создания их значения не могут быть изменены. Класс String технически не является примитивным типом данных, но, учитывая особую поддержку, предоставляемую ему языком, вы, вероятно, будете думать о нем как о таковом.Вы узнаете больше о классе String в
Простые объекты данных

Значения по умолчанию

Не всегда необходимо присваивать значение при объявлении поля. Поля, которые объявлены, но не инициализированы, будут установлены компилятором в разумные значения по умолчанию. Вообще говоря, это значение по умолчанию будет равно нулю или null , в зависимости от типа данных. Однако использование таких значений по умолчанию обычно считается плохим стилем программирования.

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

Тип Размер (байты) Диапазон
символ или знаковый знак 1-128 до 127
беззнаковый символ 110 от 0 до
Тип данных Значение по умолчанию (для полей)
байт 0
короткий 0
внутренний 0
длинный 0L
поплавок 0,0f
двойной 0,0d
символ '\ u0000'
Строка (или любой объект) null
логическое ложь

Локальные переменные немного отличаются; компилятор никогда не присваивает значение по умолчанию неинициализированной локальной переменной.Если вы не можете инициализировать свою локальную переменную там, где она объявлена, не забудьте присвоить ей значение, прежде чем пытаться использовать ее. Доступ к неинициализированной локальной переменной приведет к ошибке времени компиляции.

Литералы

Вы могли заметить, что ключевое слово new не используется при инициализации переменной примитивного типа. Примитивные типы - это особые типы данных, встроенные в язык; они не объекты, созданные из класса. Литерал - это представление исходного кода фиксированного значения; литералы представлены непосредственно в вашем коде, не требуя вычислений.Как показано ниже, можно присвоить литерал переменной примитивного типа:

логический результат = истина;
char capitalC = 'C';
байт b = 100;
короткий s = 10000;
int i = 100000;
 
Целочисленные литералы

Целочисленный литерал имеет тип длиной , если он заканчивается буквой L или l ; в противном случае это тип int . Рекомендуется использовать прописную букву L , поскольку строчную букву l трудно отличить от цифры 1 .

Значения целочисленных типов byte , short , int и long могут быть созданы из int литералов. Значения типа long , выходящие за пределы диапазона int , могут быть созданы из литералов long . Целочисленные литералы могут быть выражены с помощью этих систем счисления:

  • Десятичный: основание 10, цифры которого состоят из чисел от 0 до 9; это система счисления, которую вы используете каждый день
  • Шестнадцатеричный: основание 16, цифры которого состоят из цифр от 0 до 9 и букв от A до F
  • Двоичный: База 2, цифры которого состоят из чисел 0 и 1 (вы можете создавать двоичные литералы в Java SE 7 и более поздних версиях)

Для универсального программирования десятичная система, вероятно, будет единственной системой счисления, которую вы когда-либо будете использовать.Однако, если вам нужно использовать другую систему счисления, следующий пример показывает правильный синтаксис. Префикс 0x указывает на шестнадцатеричный, а 0b указывает на двоичный:

// Число 26 в десятичном формате
int decVal = 26;
// Число 26 в шестнадцатеричном формате
int hexVal = 0x1a;
// Число 26 в двоичном формате
int binVal = 0b11010;
 
Литералы с плавающей запятой

Литерал с плавающей запятой имеет тип float , если он заканчивается буквой F или f ; в противном случае его тип - double и может дополнительно заканчиваться буквой D или d .

Типы с плавающей запятой ( float и double ) также могут быть выражены с помощью E или e (для экспоненциальной записи), F или f (32-битный литерал с плавающей запятой) и D или d (64-битный двойной литерал; это является значением по умолчанию и по соглашению опускается).

двойной d1 = 123,4;
// то же значение, что и d1, но в экспоненциальном представлении
двойной d2 = 1.234e2;
float f1 = 123.4f;
 
Символьные и строковые литералы

Литералы типов char и Строка может содержать любые символы Unicode (UTF-16).Если ваш редактор и файловая система позволяют это, вы можете использовать такие символы непосредственно в своем коде. Если нет, вы можете использовать «escape-последовательность Unicode», например '\ u0108' (заглавная C с циркумфлексом) или «S = Se \ u00F1or» (Sí Señor на испанском языке). Всегда используйте "одинарные кавычки" для литералов char и "двойные кавычки" для литералов String . Управляющие последовательности Unicode могут использоваться в любом месте программы (например, в именах полей), а не только в литералах char или String .

Язык программирования Java также поддерживает несколько специальных escape-последовательностей для литералов char и String : \ b (backspace), \ t (tab), \ n (перевод строки), \ f (подача страницы), \ r (возврат каретки), \ " (двойная кавычка), \ ' (одинарная кавычка) и \\ (обратная косая черта).

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

Наконец, существует также особый вид литерала, называемый литералом класса , образованный путем взятия имени типа и добавления « .class» ; например, String.class .Это относится к объекту (типа , класс ), который представляет сам тип.

Использование знаков подчеркивания в числовых литералах

В Java SE 7 и более поздних версиях любое количество символов подчеркивания ( _ ) может находиться где угодно между цифрами в числовом литерале. Эта функция позволяет вам, например. для разделения групп цифр в числовых литералах, что может улучшить читаемость вашего кода.

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

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

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 3.14_15F;
длинный hexBytes = 0xFF_EC_DE_5E;
длинные шестнадцатеричные слова = 0xCAFE_BABE;
длинный maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
длинные байты = 0b11010010_01101001_10010100_10010010;
 

Знаки подчеркивания можно ставить только между цифрами; нельзя ставить подчеркивания в следующих местах:

  • В начале или конце числа
  • Рядом с десятичной точкой в ​​литерале с плавающей запятой
  • До F или L суффикс
  • В позициях, где ожидается строка цифр

В следующих примерах демонстрируются допустимые и недопустимые места подчеркивания (выделенные) в числовых литералах:

//  Недействительно: нельзя ставить подчеркивания 
//  рядом с десятичной запятой 
поплавок pi1 = 3_.1415F;
//  Недействительно: нельзя ставить подчеркивания 
//  рядом с десятичной запятой 
float pi2 = 3._1415F;
//  Недействительно: нельзя ставить подчеркивания 
//  перед суффиксом L 
long socialSecurityNumber1 = 999_99_9999_L;

// ОК (десятичный литерал)
интервал x1 = 5_2;
//  Недействительно: нельзя ставить подчеркивания 
//  В конце литерала 
int x2 = 52_;
// ОК (десятичный литерал)
int x3 = 5_______2;

//  Недействительно: нельзя ставить подчеркивания 
//  в префиксе системы счисления 0x 
int x4 = 0_x52;
//  Недействительно: нельзя ставить подчеркивания 
//  в начале числа 
int x5 = 0x_52;
// ОК (шестнадцатеричный литерал)
int x6 = 0x5_2;
//  Недействительно: нельзя ставить подчеркивания 
//  в конце числа 
int x7 = 0x52_;
 

типов данных в языке C - сумасшедший программист

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

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

Основные типы данных, которые мы использовали до сих пор, имеют некоторые ограничения. Например, мы можем хранить только значения в диапазоне от –32768 до 32767 для типа данных int. Помните, что этот диапазон предназначен для 16-битного компилятора Turbo C. Для 32-битного компилятора, такого как VC ++, этот диапазон составляет от –2147483648 до +2147483647.Вы не можете хранить больше значений, превышающих это ограничение, в типе данных int. Чтобы преодолеть эти ограничения, мы должны использовать некоторые дополнительные ключевые слова, такие как unsigned, signed и т. Д.

Что такое 16-битные и 32-битные компиляторы?
Turbo C - это 16-разрядный компилятор. После преобразования кода C в машинный язык он нацелен на выполнение этого кода на 16-битных процессорах, таких как Intel 8086.

С другой стороны, VC ++ - 32-битный компилятор. Он будет нацелен на запуск кода на 32-битных процессорах, таких как процессоры Intel Pentium.

short and long int

Как я уже говорил ранее, язык C предоставляет вариации в своих основных типах данных. short и long - это такие вариации целочисленного типа данных. Как следует из названия, long имеет больший диапазон, чем int.

Примечание: Здесь короткое и длинное оба ключевых слова.

Ниже приводится диапазон коротких и длинных позиций.

Диапазон длинных значений: от -2147483648 до 2147483647.
Диапазон коротких значений: от -32,768 до +32,767

со знаком и без знака int

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

Новый диапазон будет от 0 до 65535

По умолчанию нормальное int также называется знаком int.

знаковый и беззнаковый символ

Диапазон нормального символа - от -128 до +127. Вы должны были знать, что тип данных char всегда хранит значение символа ASCII. Часто мы оказываемся в состоянии, когда у нас есть печать или доступ к символу ASCII, значение которого больше +127.Поэтому в этом случае мы обычно используем беззнаковый символ. Подобно int, он также увеличивает диапазон почти вдвое. И знаковые, и беззнаковые символы занимают в памяти 1 байт.

Новый диапазон будет от 0 до 255

float и double

float Переменная занимает 4 байта в памяти и также обеспечивает хороший диапазон для хранения в нем значений. Это дает диапазон от -3,4e38 до + 3,4e38.

Если вы хотите увеличить этот предел, вы также можете использовать двойной тип данных. Он занимает 8 байтов в памяти, а также предоставляет очень большой диапазон для хранения значений.Его диапазон составляет от -1,7e4932 до + 1,7e4932.

Объявление всех типов данных

Ниже приведены объявления всех типов данных, которые мы изучили до сих пор.

int a;
беззнаковое int b;
long int c;
короткий int d;
unsigned short int e;
беззнаковое длинное int f;
char г;
беззнаковый символ f;
float g;
двойной ч;

Типы данных - Руководство NumPy v1.20

Типы массивов и преобразования между типами¶

NumPy поддерживает гораздо большее разнообразие числовых типов, чем Python.В этом разделе показано, какие из них доступны и как изменить тип данных массива.

Поддерживаемые типы примитивов тесно связаны с типами в C:

.

Тип Numpy

Тип C

Описание

numpy.bool_

булев

Логическое значение (Истина или Ложь) хранится в виде байта

кол-во.байт

знак со знаком

Определяется платформой

numpy.ubyte

символ без знака

Определяется платформой

numpy.short

короткий

Определяется платформой

numpy.ushort

беззнаковое короткое

Определяется платформой

кол-во.intc

внутренний

Определяется платформой

numpy.uintc

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

Определяется платформой

numpy.int_

длинный

Определяется платформой

numpy.uint

беззнаковое длинное

Определяется платформой

кол-во.Лонглун

длинный длинный

Определяется платформой

numpy.ulonglong

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

Определяется платформой

numpy.half / numpy.float16

Поплавок половинной точности:
знаковый бит, 5-битная экспонента, 10-битная мантисса

кол-во.одноместный

с плавающей запятой

Поплавок одинарной точности, определяемый платформой:
обычно знаковый бит, 8-битная экспонента, 23-битная мантисса

число. Двойное

двойной

Поплавок двойной точности, определяемый платформой:
обычно знаковый бит, 11-битная экспонента, 52-битная мантисса.

число.долг.двойное

длинный двойной

Определяемый платформой поплавок повышенной точности

кол-во.csingle

поплавковый комплекс

Комплексное число, представленное двумя числами с плавающей запятой одинарной точности (действительная и мнимая составляющие)

numpy.cdouble

двойной комплекс

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

numpy.clongdouble

длинный двойной комплекс

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

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

Числовые типы NumPy являются экземплярами объектов dtype (тип данных), каждый
обладающие уникальными характеристиками. После того, как вы импортировали NumPy, используя

типы dtypes доступны как np.bool_ , np.float32 и т. Д.

Расширенные типы, не перечисленные в таблице выше, рассматриваются в
раздел Структурированные массивы.

Существует 5 основных числовых типов, представляющих логические значения (bool), целые числа (int),
целые числа без знака (uint) с плавающей запятой (float) и комплексные. Те, у кого есть числа
в их названии указывают битовый размер типа (т.е. сколько бит необходимо
для представления единственного значения в памяти). Некоторые типы, такие как int и
intp , имеют разный размер битов в зависимости от платформ (например, 32-битный
против 64-битных машин). Это следует учитывать при сопряжении
с низкоуровневым кодом (например, C или Fortran), где адресуется необработанная память.

Типы данных могут использоваться как функции для преобразования чисел Python в скаляры массива
(см. раздел скалярных массивов для объяснения), последовательности чисел Python
для массивов этого типа или в качестве аргументов ключевого слова dtype, которое многие numpy
функции или методы принимают. Некоторые примеры:

 >>> импортировать numpy как np
>>> x = np.float32 (1.0)
>>> х
1.0
>>> y = np.int _ ([1,2,4])
>>> у
массив ([1, 2, 4])
>>> z = np.arange (3, dtype = np.uint8)
>>> г
массив ([0, 1, 2], dtype = uint8)
 

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

 >>> np.array ([1, 2, 3], dtype = 'f')
array ([1., 2., 3.], dtype = float32)
 

Вместо этого мы рекомендуем использовать объекты dtype.

Чтобы преобразовать тип массива, используйте метод .astype () (предпочтительно) или
сам тип как функция. Например:

 >>> z.astype (float)
массив ([0., 1., 2.])
>>> np.int8 (z)
array ([0, 1, 2], dtype = int8)
 

Обратите внимание, что выше мы используем объект с плавающей запятой Python как dtype.NumPy знает
что int относится к np.int_ , bool означает np.bool_ ,
что с плавающей запятой - это np.float_ , а комплексный - это np.complex_ .
Остальные типы данных не имеют эквивалентов Python.

Чтобы определить тип массива, посмотрите на атрибут dtype:

 >>> z.dtype
dtype ('uint8')
 

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

 >>> d = np.dtype (число)
>>> d
dtype ('int32')

>>> np.issubdtype (d, np.integer)
Правда

>>> np.issubdtype (d, np.floating)
Ложь
 

Скаляры массива¶

NumPy обычно возвращает элементы массивов как скаляры массива (скаляр
со связанным dtype). Скаляры массива отличаются от скаляров Python, но
по большей части они могут использоваться взаимозаменяемо (первичный
Исключение составляют версии Python старше v2.x, где целочисленный массив
скаляры не могут действовать как индексы для списков и кортежей). Есть некоторые
исключения, например, когда код требует очень специфических атрибутов скаляра
или когда он специально проверяет, является ли значение скаляром Python. В целом,
проблемы легко решаются явным преобразованием скаляров массива
в скаляры Python, используя соответствующую функцию типа Python
(например, int , float , complex , str , unicode ).

Основным преимуществом использования скаляров массива является то, что
они сохраняют тип массива (Python может не иметь соответствующего скалярного типа
в наличии, эл.грамм. int16 ). Следовательно, использование скаляров массива обеспечивает
одинаковое поведение массивов и скаляров, независимо от того,
значение находится внутри массива или нет. Скаляры NumPy также имеют много одинаковых
методы массивы делают.

Ошибки переполнения¶

Фиксированный размер числовых типов NumPy может вызывать ошибки переполнения, когда значение
требует больше памяти, чем доступно в типе данных. Например,
numpy.power правильно оценивает 100 * 10 ** 8 для 64-битных целых чисел,
но дает 1874

4 (неверно) для 32-битного целого числа.

 >>> np.power (100, 8, dtype = np.int64)
10000000000000000
>>> np.power (100, 8, dtype = np.int32)
18744
 

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

NumPy предоставляет номеров.iinfo и numpy.finfo для проверки
минимальные или максимальные значения целых чисел и значений с плавающей запятой NumPy
соответственно

 >>> np.iinfo (int) # Границы целого числа по умолчанию в этой системе.
iinfo (min = -72036854775808, max = 72036854775807, dtype = int64)
>>> np.iinfo (np.int32) # Границы 32-битного целого числа
iinfo (min = -2147483648, max = 2147483647, dtype = int32)
>>> np.iinfo (np.int64) # Границы 64-битного целого числа
iinfo (min = -72036854775808, max = 72036854775807, dtype = int64)
 

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

 >>> np.power (100, 100, dtype = np.int64) # Неправильно даже с 64-битным int
0
>>> np.power (100, 100, dtype = np.float64)
1e + 200
 

Повышенная точность¶

Числа с плавающей запятой Python обычно представляют собой 64-битные числа с плавающей запятой,
почти эквивалентно np.float64 . В некоторых необычных ситуациях это может быть
полезно использовать числа с плавающей запятой с большей точностью.Будь это
возможно в numpy, зависит от оборудования и разработки
среда: в частности, машины x86 предоставляют аппаратное обеспечение с плавающей запятой
с 80-битной точностью, и хотя большинство компиляторов C предоставляют это как свои
long double type, MSVC (стандартный для сборок Windows) делает
long double идентично double (64 бита). NumPy делает
компилятор long double доступен как np.longdouble
np.clongdouble для комплексных чисел).Вы можете узнать, что у вас
numpy предоставляет np.finfo (np.longdouble) .

NumPy не предоставляет dtype с большей точностью, чем C
длинный двойной \; в частности, 128-битная четырехъядерная точность IEEE
тип данных (FORTRAN's REAL * 16 \) недоступен.

Для эффективного выравнивания памяти обычно сохраняется np.longdouble
дополнены нулевыми битами до 96 или 128 бит. Что более эффективно
зависит от оборудования и среды разработки; обычно на 32-битном
системы они дополнены до 96 бит, в то время как в 64-битных системах они
обычно дополняется до 128 бит. np.longdouble добавлен к системе
По умолчанию; np.float96 и np.float128 предназначены для пользователей, которые
нужно конкретное заполнение. Несмотря на названия, np.float96 и
np.float128 обеспечивает такую ​​же точность, как np.longdouble ,
то есть 80 бит на большинстве машин x86 и 64 бит в стандартном
Сборки Windows.

Имейте в виду, что даже если np.longdouble предлагает большую точность, чем
python float , эту дополнительную точность легко потерять, поскольку
Python часто заставляет значения проходить через с плавающей запятой .Например,
оператор форматирования % требует преобразования своих аргументов
к стандартным типам Python, и поэтому невозможно сохранить
повышенная точность, даже если требуется много десятичных знаков. Может
будет полезно протестировать ваш код со значением
1 + np.finfo (np.longdouble) .eps .

Целочисленные объекты - документация Python 3.9.6

Все целые числа реализованы как «длинные» целочисленные объекты произвольного размера.

При ошибке большинство API PyLong_As * возвращают (тип возврата) -1 , что не может быть
отличается от числа.Используйте PyErr_Occurred () для устранения неоднозначности.

PyLongObject

Этот подтип PyObject представляет собой целочисленный объект Python.

PyTypeObject PyLong_Type

Этот экземпляр PyTypeObject представляет собой целочисленный тип Python.
Это тот же объект, что и int в слое Python.

int PyLong_Check (PyObject * p )

Вернуть истину, если его аргумент - PyLongObject или подтип
PyLongObject .Эта функция всегда успешна.

интервал PyLong_CheckExact (PyObject * p )

Вернуть истину, если его аргумент - PyLongObject , но не подтип
PyLongObject . Эта функция всегда успешна.

PyObject * PyLong_FromLong (длинный v )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из v или NULL в случае ошибки.

Текущая реализация хранит массив целочисленных объектов для всех целых чисел.
между -5 и 256 , когда вы создаете int в этом диапазоне, вы фактически
просто верните ссылку на существующий объект.

PyObject * PyLong_FromUnsignedLong (длинный беззнаковый v )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из C unsigned long , или
NULL в случае сбоя.

PyObject * PyLong_FromSsize_t (Py_ssize_t v )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из C Py_ssize_t , или
NULL в случае сбоя.

PyObject * PyLong_FromSize_t (size_t против )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из C size_t , или
NULL в случае сбоя.

PyObject * PyLong_FromLongLong (длинный длинный v )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из C long long или NULL
при неудаче.

PyObject * PyLong_FromUnsignedLongLong (unsigned long long v )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из C unsigned long long ,
или NULL в случае сбоя.

PyObject * PyLong_FromDouble (двойной против )
Возвращаемое значение: Новая ссылка.

Вернуть новый объект PyLongObject из целой части v , или
NULL в случае сбоя.

PyObject * PyLong_FromString (const char * str , char ** pend , int base )
Возвращаемое значение: Новая ссылка.

Вернуть новый PyLongObject на основе строкового значения в str , которое
интерпретируется в соответствии с основанием системы счисления .Если pend не NULL ,
* pend будет указывать на первый символ в str , который следует за
представление числа. Если base - 0 , str интерпретируется с использованием
определение целочисленных литералов; в этом случае ведущие нули в
ненулевое десятичное число вызывает ValueError . Если base не равно 0 ,
он должен находиться в диапазоне от 2 до 36 включительно. Ведущие пространства и одиночные
подчеркивания после спецификатора основания и между цифрами игнорируются.Если здесь
нет цифр, будет выдано ValueError .

PyObject * PyLong_FromUnicode (Py_UNICODE * u , Py_ssize_t длина , int база )
Возвращаемое значение: Новая ссылка.

Преобразует последовательность цифр Unicode в целочисленное значение Python.

PyObject * PyLong_FromUnicodeObject (PyObject * u , int base )
Возвращаемое значение: Новая ссылка.

Преобразование последовательности цифр Unicode в строке u в целое число Python
значение.

PyObject * PyLong_FromVoidPtr (недействительный * p )
Возвращаемое значение: Новая ссылка.

Создайте целое число Python из указателя p . Значение указателя может быть
извлекается из полученного значения с помощью PyLong_AsVoidPtr () .

длинный PyLong_AsLong (PyObject * obj )

Вернуть C long представление obj .Если obj не является
экземпляр PyLongObject , сначала вызовите его __index __ () или
__int __ () метод (если есть) для преобразования его в
PyLongObject .

Вызов OverflowError , если значение obj выходит за пределы допустимого диапазона
длинный .

В случае ошибки возвращает -1 . Используйте PyErr_Occurred () для устранения неоднозначности.

Устарело, начиная с версии 3.8: Использование __int __ () устарело.

длинный PyLong_AsLongAndOverflow (PyObject * obj , int * переполнение )

Вернуть C long представление obj . Если obj не является
экземпляр PyLongObject , сначала вызовите его __index __ () или
__int __ () метод (если есть) для преобразования его в
PyLongObject .

Если значение obj больше LONG_MAX или меньше
LONG_MIN , установите * overflow на 1 или -1 , соответственно, и
возврат -1 ; в противном случае установите * переполнение на 0 .Если любое другое исключение
происходит установка * переполнение на 0 и возврат -1 как обычно.

В случае ошибки возвращает -1 . Используйте PyErr_Occurred () для устранения неоднозначности.

Устарело, начиная с версии 3.8: Использование __int __ () устарело.

длинный длинный PyLong_AsLongLong (PyObject * obj )

Вернуть C long long представление obj .Если obj не является
экземпляр PyLongObject , сначала вызовите его __index __ () или
__int __ () метод (если есть) для преобразования его в
PyLongObject .

Вызов OverflowError , если значение obj выходит за пределы допустимого диапазона
длинный длинный .

В случае ошибки возвращает -1 . Используйте PyErr_Occurred () для устранения неоднозначности.

Устарело, начиная с версии 3.8: Использование __int __ () устарело.

long long PyLong_AsLongLongAndOverflow (PyObject * obj , int * переполнение )

Вернуть C long long представление obj . Если obj не является
экземпляр PyLongObject , сначала вызовите его __index __ () или
__int __ () метод (если есть) для преобразования его в
PyLongObject .

Если значение obj больше LLONG_MAX или меньше
LLONG_MIN , установите * overflow на 1 или -1 соответственно,
и возвращаем -1 ; в противном случае установите * переполнение на 0 .Если любой другой
возникает исключение, установите * переполнение на 0 и верните -1 как обычно.

В случае ошибки возвращает -1 . Используйте PyErr_Occurred () для устранения неоднозначности.

Устарело, начиная с версии 3.8: Использование __int __ () устарело.

Py_ssize_t PyLong_AsSsize_t (PyObject * pylong )

Вернуть C Py_ssize_t представление пилонга . пилонг ​​ сусло
быть экземпляром PyLongObject .

Вызов OverflowError , если значение пилонга выходит за пределы допустимого диапазона
Py_ssize_t .

В случае ошибки возвращает -1 . Используйте PyErr_Occurred () для устранения неоднозначности.

беззнаковый длинный PyLong_AsUnsignedLong (PyObject * pylong )

Вернуть C unsigned long представление пилонга . пилонга
должен быть экземпляром PyLongObject .

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

Возвращает (длинное без знака) -1 в случае ошибки.
Используйте PyErr_Occurred () для устранения неоднозначности.

size_t PyLong_AsSize_t (PyObject * pylong )

Вернуть C size_t представление пилонга . пилонг ​​ должен быть
экземпляр PyLongObject .

Вызов OverflowError , если значение пилонга выходит за пределы допустимого диапазона
размер_т .

Возвращает (size_t) -1 при ошибке.
Используйте PyErr_Occurred () для устранения неоднозначности.

unsigned long long PyLong_AsUnsignedLongLong (PyObject * pylong )

Вернуть C unsigned long long представление пилонга . пилонга
должен быть экземпляром PyLongObject .

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

Возвращает (unsigned long long) -1 в случае ошибки.
Используйте PyErr_Occurred () для устранения неоднозначности.

беззнаковый длинный PyLong_AsUnsignedLongMask (PyObject * obj )

Вернуть C unsigned long представление obj .Если obj
не является экземпляром PyLongObject , сначала вызовите его
__index __ () или __int __ () метод (если есть) для преобразования
это в PyLongObject .

Если значение obj выходит за пределы диапазона unsigned long ,
вернуть уменьшение этого значения по модулю ULONG_MAX + 1 .

Возвращает (длинное без знака) -1 в случае ошибки. Используйте PyErr_Occurred () для
устранять неоднозначность.

Не рекомендуется, начиная с версии 3.8: Использование __int __ () устарело.

беззнаковый длинный длинный PyLong_AsUnsignedLongLongMask (PyObject * obj )

Вернуть C unsigned long long представление obj . Если obj
не является экземпляром PyLongObject , сначала вызовите его
__index __ () или __int __ () метод (если есть) для преобразования
это в PyLongObject .

Если значение obj выходит за пределы диапазона unsigned long long ,
вернуть уменьшение этого значения по модулю ULLONG_MAX + 1 .

Возвращает (unsigned long long) -1 в случае ошибки. Используйте PyErr_Occurred ()
чтобы устранить неоднозначность.

Устарело, начиная с версии 3.8: Использование __int __ () устарело.

двойной PyLong_AsDouble (PyObject * pylong )

Вернуть C double представление пилонга . пилонг ​​ должен быть
экземпляр PyLongObject .

Вызов OverflowError , если значение пилонга выходит за пределы допустимого диапазона
двойной .

Возвращает -1,0 в случае ошибки. Используйте PyErr_Occurred () для устранения неоднозначности.

void * PyLong_AsVoidPtr (PyObject * pylong )

Преобразует целое число Python pylong в указатель C void .
Если пилонга не может быть преобразовано, будет вызвана ошибка OverflowError .

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

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