stringtranslate.com

Типы данных C

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

Язык C предоставляет базовые арифметические типы, такие как типы целых и действительных чисел , а также синтаксис для построения массивов и составных типов. Заголовки стандартной библиотеки C , которые будут использоваться через директивы include , содержат определения типов поддержки, которые имеют дополнительные свойства, такие как предоставление хранилища точного размера, независимо от реализации языка на конкретных аппаратных платформах. [1] [2]

Основные типы

Основные типы

Язык C предоставляет четыре основных спецификатора арифметических типов char , int , float и double , а также модификаторы Signed , Unsigned , Short и Long . В следующей таблице перечислены допустимые комбинации при указании большого набора объявлений, зависящих от размера хранилища.

  1. ^ abcde Минимальные диапазоны от −(2 n −1 −1) до 2 n −1 −1 (например, [−127,127]) происходят из различных целочисленных представлений, разрешенных стандартом ( дополнение единиц , величина знака , дополнение до двух ) . . [4] Однако большинство платформ используют дополнение до двух, подразумевая диапазон от -2 m -1 до 2 m -1 -1 с m  ≥  n для этих реализаций, например [-128,127] ( SCHAR_MIN = -128 и SCHAR_MAX = 127) для 8-битного знакового символа . Начиная с C23, единственным допустимым представлением является дополнение до двух, поэтому значения варьируются от -2 n -1 до 2 n -1 -1 . [5]
  2. ^ Эти строки форматирования также существуют для форматирования текста, но работают с двойным числом.
  3. ^ ab Прописные буквы отличаются от строчных при выводе. Спецификаторы верхнего регистра выдают значения в верхнем регистре, а строчные — в нижнем (%A, %E, %F, %G выдают такие значения, как INF, NAN и E (экспонента) в верхнем регистре).

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

Требования к отношению заключаются в том, что long longне меньше long, которое не меньше int, которое не меньше short. Поскольку charразмер всегда является минимальным поддерживаемым типом данных, никакие другие типы данных (кроме битовых полей ) не могут быть меньше.

Минимальный размер для char— 8 бит, минимальный размер для shortи int— 16 бит, ибо longон 32 бита и long longдолжен содержать не менее 64 бит.

Тип intдолжен быть целочисленным, с которым целевой процессор работает наиболее эффективно. Это обеспечивает большую гибкость: например, все типы могут быть 64-битными. Однако популярны несколько различных схем целочисленной ширины (моделей данных). Поскольку модель данных определяет, как взаимодействуют различные программы, в рамках данного интерфейса приложения операционной системы используется единая модель данных. [9]

На практике charобычно имеют размер 8 бит и shortобычно 16 бит (как и их беззнаковые аналоги). Это справедливо для таких разнообразных платформ, как SunOS  4 Unix 1990-х годов, Microsoft MS-DOS , современный Linux и Microchip MCC18 для встроенных 8-битных микроконтроллеров PIC . POSIX требует char, чтобы размер файла составлял ровно 8 бит. [10] [11]

Различные правила стандарта C делают unsigned charбазовый тип, используемый для массивов, подходящим для хранения произвольных объектов, не являющихся битовыми полями: отсутствие битов заполнения и представлений ловушек, определение представления объекта [ 7] и возможность псевдонимов. [12]

Фактический размер и поведение типов с плавающей запятой также зависят от реализации. Единственное требование — это long doubleне меньше double, то есть не меньше float. Обычно для и используются 32-битные и 64-битные двоичные форматы с плавающей запятой IEEE 754 соответственно.floatdouble

Стандарт C99 включает новые реальные типы с плавающей запятой float_tи double_t, определенные в <math.h>. Они соответствуют типам, используемым для промежуточных результатов выражений с плавающей запятой, когда FLT_EVAL_METHODравно 0, 1 или 2. Эти типы могут быть шире, чем long double.

В C99 также добавлены сложные типы: float _Complex, double _Complex, long double _Complex. В C11 добавлены мнимые типы (описанные в информативном приложении к C99): float _Imaginary, double _Imaginary, long double _Imaginary. Включение заголовка <complex.h>позволяет получить доступ ко всем этим типам с помощью complexи imaginaryсоответственно.

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

В C99 добавлен логический тип (истина/ложь) _Bool. Кроме того, <stdbool.h>заголовок определяет boolудобный псевдоним для этого типа, а также предоставляет макросы для trueи false. _Boolфункционирует аналогично обычному целочисленному типу, за одним исключением: любые присвоения a, _Boolотличные от 0 (ложь), сохраняются как 1 (истина). Такое поведение существует для того, чтобы избежать целочисленного переполнения при неявных сужающих преобразованиях. Например, в следующем коде:

беззнаковый символ b = 256 ;    if ( b ) { /* сделать что-нибудь */ }  

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

_Bool б = 256 ;   if ( b ) { /* сделать что-нибудь */ }  

Тип _Bool также гарантирует, что истинные значения всегда сравниваются равными друг другу:

_Bool а = 1 , б = 2 ;      if ( a == b ) { /* этот код будет работать */ }    

Целочисленные типы с точностью до бита

Начиная с C23 , язык позволяет программисту определять целые числа, ширина которых составляет произвольное количество бит. Эти типы обозначаются как , где N — целочисленное константное выражение, обозначающее количество битов, включая знаковый бит для знаковых типов, представленных в дополнении до двух. Максимальное значение N обеспечивается и составляет не менее . Следовательно, тип (или ) принимает значения от -2 до 1, а значения от 0 до 3. Тип также существует, имея значение 0 или 1, и не имеет эквивалентного знакового типа. [13]_BitInt(N)BITINT_MAXWIDTHULLONG_WIDTH_BitInt(2)signed _BitInt(2)unsigned _BitInt(2)unsigned _BitInt(1)

Типы различий в размерах и указателях

Спецификация языка C включает typedef и для представления величин , связанных с памятью. Их размер определяется в соответствии с арифметическими возможностями целевого процессора, а не возможностями памяти, такими как доступное адресное пространство. Оба этих типа определены в заголовке ( в C++).size_tptrdiff_t<stddef.h>cstddef

size_t— это целочисленный тип без знака, используемый для представления размера любого объекта (включая массивы) в конкретной реализации. Оператор sizeof возвращает значение типа . Максимальный размер предоставляется через макроконстанту, которая определена в заголовке ( header в C++). гарантированно будет иметь ширину не менее 16 бит. Кроме того, POSIX включает , который представляет собой целочисленный тип со знаком той же ширины, что и .size_tsize_tSIZE_MAX<stdint.h>cstdintsize_tssize_tsize_t

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

Интерфейс к свойствам базовых типов

Информация о фактических свойствах основных арифметических типов, таких как размер, предоставляется через макроконстанты в двух заголовках: <limits.h>заголовок ( climitsheader в C++) определяет макросы для целочисленных типов, а <float.h>заголовок ( cfloatheader в C++) определяет макросы для типов с плавающей запятой. . Фактические значения зависят от реализации.

Свойства целочисленных типов

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

Целочисленные типы фиксированной ширины

Стандарт C99 включает определения нескольких новых целочисленных типов для повышения переносимости программ. [2] Уже доступные базовые целочисленные типы были сочтены недостаточными, поскольку их фактические размеры определяются реализацией и могут различаться в разных системах. Новые типы особенно полезны во встроенных средах , где оборудование обычно поддерживает только несколько типов и эта поддержка варьируется в зависимости от среды. Все новые типы определяются в <inttypes.h>заголовке ( cinttypesheader в C++), а также доступны в <stdint.h>заголовке ( cstdintheader в C++). Типы можно сгруппировать в следующие категории:

В следующей таблице приведены типы и интерфейсы для получения подробной информации о реализации ( n относится к количеству битов):

Спецификаторы формата Printf и scanf

Заголовок <inttypes.h>( cinttypesв C++) предоставляет функции, расширяющие функциональность типов, определенных в <stdint.h>заголовке. Он определяет макросы для строк формата printf и спецификаторы строк формата scanf , соответствующие типам, определенным в <stdint.h>и несколько функций для работы с типами intmax_tи uintmax_t. Этот заголовок был добавлен в C99 .

Строка формата Printf

Макросы имеют формат . Здесь {fmt} определяет форматирование вывода и может быть одним из следующих значений (десятичный), (шестнадцатеричный), (восьмеричный), (беззнаковый) и (целый). {type} определяет тип аргумента и может быть одним из , , , , , где соответствует количеству битов в аргументе.PRI{fmt}{type}dxouinFASTnLEASTnPTRMAXn

Строка формата Scanf

Макросы имеют формат . Здесь {fmt} определяет форматирование вывода и может быть одним из следующих значений (десятичный), (шестнадцатеричный), (восьмеричный), (беззнаковый) и (целый). {type} определяет тип аргумента и может быть одним из , , , , , где соответствует количеству битов в аргументе.SCN{fmt}{type}dxouinFASTnLEASTnPTRMAXn

Функции

Дополнительные типы с плавающей запятой

Подобно целочисленным типам фиксированной ширины, ISO/IEC TS 18661 определяет типы с плавающей запятой для обмена IEEE 754 и расширенные форматы в двоичном и десятичном формате:

Структуры

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

struct Birthday { имя символа [ 20 ]; международный день ; внутренний месяц ; int год ; };      структура дня рождения Джона ;  

Расположение структуры в памяти — это проблема реализации языка для каждой платформы с некоторыми ограничениями. Адрес памяти первого члена должен совпадать с адресом самой структуры. Структуры могут быть инициализированы или назначены с использованием составных литералов. Функция может напрямую возвращать структуру, хотя во время выполнения это часто неэффективно. Начиная с C99 , структура может также заканчиваться гибким элементом массива .

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

структура узла { интервал val ; структура узла * следующий ; };     

Массивы

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

интервал кот [ 10 ]; // массив из 10 элементов, каждый типа int  

Массивы можно инициализировать с помощью составного инициализатора, но не присваивать. Массивы передаются функциям путем передачи указателя на первый элемент. Многомерные массивы определяются как «массив массива…» , и все измерения, кроме самого внешнего, должны иметь постоянный размер времени компиляции:

интервал а [ 10 ][ 8 ]; // массив из 10 элементов, каждый типа 'массив из 8 элементов int'  

Указатели

Каждый тип данных Tимеет соответствующий указательT типа . Указатель — это тип данных, который содержит адрес места хранения переменной определенного типа. Они объявляются с помощью *декларатора типа звездочки ( ), следующего за базовым типом хранилища и предшествующего имени переменной. Пробелы до или после звездочки не являются обязательными.

символ * квадрат ; длинный * круг ; интервал * овал ;   

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

символ * ПК [ 10 ]; // массив из 10 элементов 'указателя на char' char ( * pa )[ 10 ]; // указатель на массив из 10 элементов char    

Элементу pcтребуется десять блоков памяти размером с указательchar (обычно 40 или 80 байт на обычных платформах), но элемент paпредставляет собой только один указатель (размером 4 или 8 байт), а данные, на которые он ссылается, представляют собой массив из десяти байтов. ( ).sizeof *pa == 10

Союзы

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

союз { интервал я ; плавать f ; структура { беззнаковый интервал и ; двойной д ; } с ; } ты ;         

Общий размер — uэто размер u.s, который является суммой размеров u.s.uи u.s.d, поскольку sон больше, чем iи f. При присвоении чего-либо u.i, некоторые части u.fмогут быть сохранены, если u.iоно меньше u.f.

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

Указатели функций

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

int ( * my_int_f ) ( int ) = & abs ; // оператор & можно опустить, но он ясно дает понять, что здесь используется «адрес» abs   

Указатели на функции вызываются по имени, как и обычные вызовы функций. Указатели на функции отличаются от указателей и указателей void .

Спецификаторы типа

Вышеупомянутые типы могут быть дополнительно охарактеризованы квалификаторами типа , что дает квалифицированный тип . Начиная с 2014 года и C11 , в стандарте C есть четыре квалификатора типа: const( C89 ), volatile( C89 ), restrict( C99 ) и _Atomic( C11 ) — последний имеет частное имя, чтобы избежать конфликта с именами пользователей, [14] но чем больше atomicможно использовать обычное имя , если <stdatomic.h>включен заголовок. Из них, constбезусловно, самый известный и наиболее используемый, появляющийся в стандартной библиотеке и встречающийся при любом значительном использовании языка C, который должен удовлетворять const-correctness . Остальные квалификаторы используются для низкоуровневого программирования и, хотя там широко используются, типичными программистами они используются редко. [ нужна цитата ]

Смотрите также

Рекомендации

  1. ^ Барр, Майкл (2 декабря 2007 г.). «Портативные целые числа фиксированной ширины в C» . Проверено 18 января 2016 г.
  2. ^ ab Спецификация ISO / IEC 9899: 1999, TC3 (PDF) . п. 255, § 7.18 Целочисленные типы <stdint.h> .
  3. ^ abcdefghij Спецификация ISO/IEC 9899:1999, TC3 (PDF) . п. 22, § 5.2.4.2.1 Размеры целочисленных типов <limits.h> .
  4. ^ Обоснование международного стандарта — Языки программирования — C, версия 5.10 (PDF) . п. 25, § 5.2.4.2.1 Размеры целочисленных типов <limits.h> .
  5. ^ Проект спецификации ISO/IEC 9899:2023 (PDF) . п. 41, § 6.2.6 Представления типов .
  6. ^ «Целочисленные ограничения C и C++» . 21 июля 2023 г.
  7. ^ ab Спецификация ISO / IEC 9899: 1999, TC3 (PDF) . п. 37, § 6.2.6.1 Представления типов – Общие сведения .
  8. ^ abcdef спецификация ISO/IEC 9899:1999, TC3 (PDF) . п. 56, § 6.4.4.1 Целочисленные константы .
  9. ^ «64-битные модели программирования: почему LP64?». Открытая группа . Проверено 9 ноября 2011 г.
  10. ^ «Ширина шрифта (Библиотека GNU C)» . www.gnu.org . Проверено 30 июля 2022 г.
  11. ^ "<limits.h>". pubs.opengroup.org . Проверено 30 июля 2022 г.
  12. ^ Спецификация ISO/IEC 9899:1999, TC3 (PDF) . п. 67, § 6.5 Выражения .
  13. ^ Проект спецификации ISO/IEC 9899:2023 (PDF) . п. 37, § 6.2.5 Типы .
  14. ^ C11: Новый стандарт C, Томас Плам