Struct в си: Сложные типы данных в Си : структуры, объединения, битовые поля

struct (C++) | Microsoft Learn

Twitter LinkedIn Facebook Адрес электронной почты

  • Статья
  • Чтение занимает 2 мин

Ключевое struct слово определяет тип структуры и /или переменную типа структуры.

Синтаксис

[template-spec] struct [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];
[struct] tag declarators;
Параметры

спецификация шаблона
Необязательные спецификации шаблона. Дополнительные сведения см. в спецификациях шаблонов.

struct
ключевое слово struct;

ms-decl-spec
Необязательная спецификация класса хранения. Дополнительные сведения см. в ключевом слове __declspec .

Тег
Имя типа, присваиваемое структуре. Тег становится зарезервированным ключевым словом в области структуры. Тег является необязательным. Если он опущен, определяется анонимная структура. Дополнительные сведения см. в разделе «Типы анонимных классов».

base-list
Необязательный список классов или структур, из которых эта структура будет наследовать члены. Дополнительные сведения см. в разделе «Базовые классы «. Перед каждым базовым классом или именем структуры может предшествовать описатель доступа (открытый, частный, защищенный) и виртуальный ключевое слово. Дополнительные сведения см. в таблице доступа к членам класса в разделе «Управление доступом к членам класса «.

member-list
Список членов структуры. Дополнительные сведения см . в обзоре элемента класса . Единственное различие здесь заключается в том, что struct используется вместо class.

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

Тип структуры — это пользовательский составной тип. Он состоит из полей или членов, которые могут иметь разные типы.

В C++структура совпадает с классом, за исключением того, что его члены по public умолчанию.

Сведения об управляемых классах и структурых в C++/CLI см. в разделе «Классы и структуры».

Использование структуры

В C необходимо явно использовать ключевое struct слово для объявления структуры. В C++не нужно использовать ключевое struct слово после определения типа.

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

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

Дополнительные сведения см. в разделе «Класс», «Объединение» и «Перечисление».

Пример

#include <iostream>
using namespace std;
struct PERSON {   // Declare PERSON struct type
    int age;   // Declare member types
    long ss;
    float weight;
    char name[25];
} family_member;   // Define object of type PERSON
struct CELL {   // Declare CELL bit field
    unsigned short character  : 8;  // 00000000 ????????
    unsigned short foreground : 3;  // 00000??? 00000000
    unsigned short intensity  : 1;  // 0000?000 00000000
    unsigned short background : 3;  // 0???0000 00000000
    unsigned short blink      : 1;  // ?0000000 00000000
} screen[25][80];       // Array of bit fields
int main() {
    struct PERSON sister;   // C style structure declaration
    PERSON brother;   // C++ style structure declaration
    sister.
age = 13; // assign values to members brother.age = 7; cout << "sister.age = " << sister.age << '\n'; cout << "brother.age = " << brother.age << '\n'; CELL my_cell; my_cell.character = 1; cout << "my_cell.character = " << my_cell.character; } // Output: // sister.age = 13 // brother.age = 7 // my_cell.character = 1

ARMCC. Структуры, обьединение, перечисление, и битовые поля в ARM C и C++

Рассматривается реализация структурных типов данных union, enum, и struct. Так же рассматривается заполнение структур и реализацию битового поля.

Unions (обьединение)

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

Enumerations (перечисление)

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

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

  • unsigned char если не используется --enum_is_int
  • signed char если не используется --enum_is_int
  • unsigned short если не используется --enum_is_int
  • signed short если не используется --enum_is_int
  • signed int
  • unsigned int кроме Си  с --strict
  • signed long long
    кроме Си  с --strict
  • unsigned long long кроме Си  с --strict.

Примечание

  • В RVCT 4.0, тип хранилища enum являющийся первым беззнаковым типом из списка применяется только в режиме GNU (--gnu).
  • В ARM® Compiler 4.1 и выше, тип хранения перечисления enum тип хранения перечисления, являющийся первым беззнаковым типом из списка, применяется независимо от режима.

Реализация enum таким образом может уменьшать размер данных. Опция командной строки --enum_is_int lделает основной тип enum наименьшой шириной  int.

See the description of C language mappings in the Procedure Call Standard for the ARM® Architecture specification for more information.

Примечание

Care must be taken when mixing translation units that have been compiled with and without the --enum_is_int option, and that share interfaces or data structures.

In strict C, enumerator values must be representable as ints. That is, they must be in the range -2147483648 to +2147483647, inclusive. A warning is issued for out-of-range enumerator values:

#66: enumeration value is out of "int" range

Such values are treated the same way as in C++, that is, they are treated as unsigned
int
, long long, or unsigned long
long
.

To ensure that out-of-range Warnings are reported, use the following command to change them into Errors:

armcc --diag_error=66 ...

Structures (структуры)

Следующие пункты относятся к :

  • все структуры Си
  • все C++ структуры и классы не использующие виртуальные или базовые классы.

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

На графике 1 показан пример классической неупакованной структуры.

Байты 1, 2, и 3 заполняются чтобы обеспечить правильное выравнивание поля.

Байты 11 и 12 заполняются чтобы обеспечить правильное выравнивание структуры.

Функция sizeof() возвращает размер структуры включающая заполнение.

График 1 Пример обычной неупакованной структуры

 

Компилируются структуры одним из способов в зависимости от ее определения:

  • Структуры которые определены как static или  extern
    заполняются нулями.
  • Структуры в стеке или куче, например которые определены с помощью malloc() или auto, заполняются тем что хранилось в памяти ранее. Вы не можете использовать функцию memcmp() для сравнения содержимого структур определенных таким образом.

Используйте опцию --remarks для просмотра сообщений генерируемых компилятором когда он вставляет дополнения в структуру struct.

Структуры с пустой инициализацией разрешены в  C++:

struct
{
    int x;
} X = { };

Однако, если вы компилируете C или C++ с параметрами — cpp и — c90, генерируется ошибка.

Bitfields (битовое поле)

В неупакованных структурах, ARM компилятор выделяет битовые поля в контейнеры.

Контейнер как корректно выравненный обьект декларируемого типа.

Битовые поля распределяются таким образом, чтобы указанное первое поле занимало младшие биты слова в зависимости от конфигурации::

Little-endian
Самые низкие адресации являются наименее значимыми.
Big-endian
Самые низкие адресации являются наиболее значимыми.

Контейнер битового поля может быть любым целым типом.

Примечание

In strict 1990 ISO Standard C, the only types permitted for a bit field are int, signed int, and unsigned int. For non-int bitfields, the compiler displays an error.

В строгом стандарте ISO стандартного стандарта 1990 года единственными типами, разрешенными для битового  поля, являются int, signed int, и unsigned int. Для не —int битового поля компилятор отображает ошибку.

Простое битовое поле, обьявленное без signed или unsigned квалификаторов, рассматривается как unsigned. Для примера, int x:10 выделяется как целое число  без знака  размером 10 бит.

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

struct X
{
    int x:10;
    int y:20;
};

В первом объявлении создается целочисленный контейнер и выделяется 10 бит в x. Во втором объявлении компилятор находит существующий целочисленный контейнер с достаточным количеством нераспределенных битов и выделяет y в том же контейнере, что и x.

Битовое поле полностью содержится в контейнере. Битовое поле, которое не помещается в контейнер, помещается в следующий контейнер того же типа.

Например, декларация z переполняет контейнер, если для структуры объявлено дополнительное битовое поле:

struct X
{
    int x:10;
    int y:20;
    int z:5;
};

Компилятор заполняет оставшиеся два бита для первого контейнера и назначает новый целочисленный контейнер для z.

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

struct X
{
    int x:10;
    char y:2;
};

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

Поскольку естественное выравнивание символа равно 1, компилятор выполняет поиск первого байта, который содержит достаточное количество нераспределенных битов, чтобы полностью содержать бит.  В структуре примера второй байт контейнера int имеет два бита, выделенных для x, и 6 бит нераспределены. Компилятор выделяет контейнер char  начиная со второго байта предыдущего int контейнера, пропускает первые два бита, которые выделены для x, и выделяет два бита в y.

Если y объявлен char y: 8, компилятор заполняет второй байт и выделяет новый контейнер символов в третий байт, потому что битовое поле не может переполнять его контейнер. На следующем рисунке показано распределение битового поля для следующего примера структуры:

struct X
{
    int x:10;
    char y:8;
};

Распределение битового поля

 

Примечение

Те же основные правила применяются к объявлениям битового поля с разными типами контейнеров. Например, добавим битовое полеint к структуре и она примет следующий вид:

struct X
{
    int x:10;
    char y:8;
    int z:5;
}

Компилятор выделяет контейнер int, начинающийся в том же месте, что и контейнер int x:10, и выделяет байт-выровненный char и 5-битное битовое поле как показано ниже:

Распределение битового поля

 

Вы можете явно помещать контейнер битового поля, объявляя неопределенное битовое поле размером 0. Битовое поле нулевого размера заполняет контейнер до конца, если контейнер не пуст. Последующее объявление битового поля запускает новый пустой контейнер.

Примечание

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

Packing and alignment of bitfields (упаковка и выравнивание битовых полей)

 

Использование __attribute__((aligned(n))) делает битовое поле n-байт выравненным, не только его контейнер, but the bitfield is aligned to the packed alignment at most. It is ignored on bitfields in __packed and __attribute__((packed)) structs.

The alignment of a bitfield member’s container is the same as the alignment of that bitfield member. The size of a bitfield container is the least multiple of the alignment that fully covers the bitfield, but no larger than the size of the container-type. The following code examples show this:

#pragma pack(2)
/* Контейнер b должен начинаться с границы выравнивания 2 байта и должен 
* иметь размер не больше, чем тип контейнера, в этом случае размер 
* короткий. Контейнер b не может начинаться со смещения 0 (перекрывается с a) 
*, так как бит b будет начинаться со смещения 2 и не будет полностью лежать 
* внутри контейнера. Поэтому контейнер для b должен начинаться со смещения 
* 2.
*
* Data layout:      0x11 0x00 0x22 0x22
* Container layout:| a  |    |    b    |   
*/
struct { 
  char a;
  short b : 16;
} var1 = { 0x11, 0x2222 };
  
      
/* контейнер b может быть до 4 байт. Его размер должен быть 2 или 4 байта, так как они являются кратны*  ми выравниванию, которые не больше размера контейнера. При использовании 4 байтового контейнера 
*, начинающегося с 0, битовое поле b может начинаться со смещения 1 и полностью лежать 
*  внутри контейнера. 
*
* Data layout:      0x11 0x22 0x22 0x00
* Container layout:| a  |
*                  |         b         |
*/
struct { 
  char a;
  int b : 16;
} var2 = { 0x11, 0x2222 };

Упакованные контейнеры битовых полей, включая все контейнеры битовых полей в упакованных структурах, имеют выравнивание 1. Поэтому максимальное битовое дополнение, вставленное для выравнивания упакованного контейнера битовых полей, составляет 7 бит.

Для неупакованного контейнера битового поля, максимальное заполнение битов 8*sizeof(container-type)-1.

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

A packed bitfield container is only large enough (in bytes) to hold the bitfield that declared it. Non-packed bitfield containers are the size of their type.

Следующие примеры иллюстрируют эти взаимодействия.

struct A {          int z:17; }; // sizeof(A) = 4, alignment = 4
struct A { __packed int z:17; }; // sizeof(A) = 3, alignment = 1
__packed struct A { int z:17; }; // sizeof(A) = 3, alignment = 1
struct A { char y:1;          int z:31; }; // sizeof(A) = 4, alignment = 4
struct A { char y:1; __packed int z:31; }; // sizeof(A) = 4, alignment = 1
__packed struct A { char y:1; int z:31; }; // sizeof(A) = 4, alignment = 1
struct A { char y:1;          int z:32; }; // sizeof(A) = 8, alignment = 4
struct A { char y:1; __packed int z:32; }; // sizeof(A) = 5, alignment = 1
__packed struct A { char y:1; int z:32; }; // sizeof(A) = 5, alignment = 1
struct A { int x; char y:1;          int z:31; };  // sizeof(A) = 8, alignment = 4
struct A { int x; char y:1; __packed int z:31; };  // sizeof(A) = 8, alignment = 4
__packed struct A { int x; char y:1; int z:31; };  // sizeof(A) = 8, alignment = 1
struct A { int x; char y:1;          int z:32; };  // sizeof(A) = 12, alignment = 4 [1]
struct A { int x; char y:1; __packed int z:32; };  // sizeof(A) = 12, alignment = 4 [2]
__packed struct A { int x; char y:1; int z:32; };  // sizeof(A) = 9, alignment = 1

Note that [1] and [2] are not identical; the location of z within the structure and the tail-padding differ.

struct example1
{
int a : 8;  /* 4-byte container at offset 0 */
__packed int b : 8;  /* 1-byte container at offset 1 */
__packed int c : 24; /* 3-byte container at offset 2 */
}; /* Total size 8 (3 bytes tail padding) */;
struct example2
{
__packed int a : 8; /* 1-byte container at offset 0 */
__packed int b : 8; /* 1-byte container at offset 1 */
int c : 8; /* 4-byte container at offset 0 */
}; /* Total size 4 (No tail padding) */
struct example3
{
int a : 8;  /* 4-byte container at offset 0 */
__packed int b : 32; /* 4-byte container at offset 1 */
__packed int c : 32; /* 4-byte container at offset 5 */
int d : 16; /* 4-byte container at offset 8 */
int e : 16; /* 4-byte container at offset 12 */
int f : 16; /* In previous container */
}; /* Total size 16 (No tail padding) */

C Примеры

❮ Предыдущий Далее ❯


Синтаксис

Создайте простую программу «Hello World»

Объяснение синтаксиса


Вывод/Печать

Используйте printf для печати текста Использование многих функций printf Вставьте новую строку с \n

Объяснение вывода


Комментарии

Однострочный комментарий перед строкой кода Однострочный комментарий в конце строки кода Многострочный комментарий

Объяснение комментариев


Переменные

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

Описание переменных


Типы данных и спецификаторы формата

Демонстрация различных типов данных и спецификаторов формата

Описание типов данных и спецификаторов формата



Операторы

Оператор сложения Оператор вычитания Оператор отдела Оператор модуля Оператор приращения Оператор декремента Оператор присваивания Оператор присваивания сложения Оператор сравнения Логические операторы

Описание операторов


If.

..Else (условия)

Оператор если Оператор else Оператор else if

If… Else Объяснение


Switch

Оператор switch Оператор switch с ключевым словом по умолчанию

Объяснение переключателя


Циклы

Пока цикл Выполнить цикл while Для цикла Разорвать петлю Продолжить цикл

Объяснение циклов


Массивы

Создание и доступ к массиву Изменить элемент массива Цикл по массиву

Объяснение массивов


Строки

Создать строку Другой способ создать строку Символы строки доступа Изменение символов строки

Объяснение строк


Пользовательский ввод

Введите число и распечатайте результат Введите два числа и распечатайте сумму

Объяснение пользовательского ввода


Адрес памяти/ссылки

Получить адрес памяти переменной

Объяснение адреса памяти


Указатели

Создайте переменную указателя Получить значение переменной с помощью оператора разыменования *

Объяснение указателей


Функции

Создать и вызвать функцию Вызов функции несколько раз Объявление и определение функции Параметры и аргументы Несколько параметров Возвращаемое значение Возвращает сумму двух параметров Рекурсия (сделать вызов самой функции) Используйте математическую функцию, чтобы получить квадратный корень из числа

Описание функций


Конструкции

Доступ к структуре Создайте несколько структурных переменных с разными значениями Строка в структуре Упрощенный синтаксис (сокращение) Копировать значения структуры Изменить значения Пример из реальной жизни

Описание структур


❮ Предыдущий Следующий ❯


ВЫБОР ЦВЕТА



Лучшие учебники
Учебник HTML
Учебник CSS
Учебник JavaScript
Учебник How To
Учебник SQL
Учебник Python
Учебник по W3. CSS
Учебник по Bootstrap
Учебник по PHP
Учебник по Java
Учебник по C++
Учебник по jQuery

Основные ссылки
Справочник по HTML
Справочник по CSS
Справочник по JavaScript
Справочник по SQL
Справочник по Python
Справочник по W3.CSS
Справочник по Bootstrap
Справочник по PHP
Цвета HTML
Справочник по Java
Справочник по Angular
Справочник по jQuery

Лучшие примеры Примеры HTML

Примеры CSS
Примеры JavaScript
Примеры инструкций
Примеры SQL
Примеры Python
Примеры W3.CSS
Примеры Bootstrap
Примеры PHP
Примеры Java
Примеры XML
Примеры jQuery


FORUM | О

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

Copyright 1999-2022 Refsnes Data. Все права защищены.
W3Schools работает на основе W3.CSS.

Простое руководство по использованию структур в C

Автор Джером Дэвидсон

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

Структура (или структура) — это смешанный тип данных в C. Вы можете использовать его для хранения переменных разных типов.

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

Создание структуры

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

 struct Car{ 
char name[45];
внутр колеса;
двойная стоимость;
} ;

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

 struct Car{ 
/* переменные */
} Car1, Car2, Car3;

Вы также можете вложить структуру в структуру. См. пример ниже:

 адрес структуры { 
int area_code;
символов имя_улицы[45];
};
struct Person {
char name[60];
высота поплавка;
адрес структуры Persons_location;
};

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

Операции над типами структур

Инициализация

Существует три способа инициализации элементов структуры.

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

 struct Car Car1 = {"Грузовик", 10, 65000}; 

Связано: Руководство для начинающих по стандартной библиотеке шаблонов в C++

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

 struct Car Car2 = { 
.cost = 45000,
.name = "Грузовик",
.wheels = 8
};

Третий способ инициализировать вашу структуру — назначить ей существующую структуру того же типа.

 структура Автомобиль Автомобиль3 = Автомобиль1; 

Доступ к элементам структуры

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

 /* синтаксис: 
structName.elementName */
int y = Car1.wheels;

Взгляд на объектно-ориентированное программирование

Как упоминалось в начале, структура сравнима с использованием классов в объектно-ориентированном программировании (ООП).

Оставить комментарий

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

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