Массивы позволяют определить тип переменных, которые могут содержать несколько элементов данных одного вида. Аналогичным образом структура — это еще один определяемый пользователем тип данных, доступный в C, который позволяет объединять элементы данных разных типов.
Структуры используются для представления записи. Предположим, вы хотите отслеживать свои книги в библиотеке. Вы можете отслеживать следующие атрибуты о каждой книге —
- заглавие
- автор
- Предмет
- ID книги
Определение структуры
Чтобы определить структуру, вы должны использовать инструкцию struct . Оператор struct определяет новый тип данных с более чем одним членом. Формат оператора структуры следующий:
struct [structure tag] { member definition; member definition; ... member definition; } [one or more structure variables];
Тег структуры является необязательным, и каждое определение члена является обычным определением переменной, например int i; или плавать f; или любое другое допустимое определение переменной. В конце определения структуры перед последней точкой с запятой вы можете указать одну или несколько переменных структуры, но это не обязательно. Вот как вы бы объявили структуру Книги —
struct Books { char title[50]; char author[50]; char subject[100]; int book_id; } book;
Доступ к членам структуры
Чтобы получить доступ к любому члену структуры, мы используем оператор доступа к члену (.) . Оператор доступа к элементу кодируется как точка между именем структурной переменной и элементом структуры, к которому мы хотим получить доступ. Вы бы использовали ключевое слово struct для определения переменных типа структуры. В следующем примере показано, как использовать структуру в программе.
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info */ printf( "Book 1 title : %s\n", Book1.title); printf( "Book 1 author : %s\n", Book1.author); printf( "Book 1 subject : %s\n", Book1.subject); printf( "Book 1 book_id : %d\n", Book1.book_id); /* print Book2 info */ printf( "Book 2 title : %s\n", Book2.title); printf( "Book 2 author : %s\n", Book2.author); printf( "Book 2 subject : %s\n", Book2.subject); printf( "Book 2 book_id : %d\n", Book2.book_id); return 0; }
Когда приведенный выше код компилируется и выполняется, он дает следующий результат —
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
Структуры как аргументы функций
Вы можете передать структуру в качестве аргумента функции так же, как передаете любую другую переменную или указатель.
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; /* function declaration */ void printBook( struct Books book ); int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info */ printBook( Book1 ); /* Print Book2 info */ printBook( Book2 ); return 0; } void printBook( struct Books book ) { printf( "Book title : %s\n", book.title); printf( "Book author : %s\n", book.author); printf( "Book subject : %s\n", book.subject); printf( "Book book_id : %d\n", book.book_id); }
Когда приведенный выше код компилируется и выполняется, он дает следующий результат —
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
Указатели на структуры
Вы можете определять указатели на структуры так же, как вы определяете указатель на любую другую переменную —
struct Books *struct_pointer;
Теперь вы можете сохранить адрес структурной переменной в указанной выше переменной-указателе. Чтобы найти адрес структурной переменной, поместите ‘&’; оператор перед именем структуры следующим образом —
struct_pointer = &Book1;
Чтобы получить доступ к членам структуры, используя указатель на эту структуру, вы должны использовать оператор → следующим образом:
struct_pointer->title;
Давайте перепишем приведенный выше пример, используя указатель структуры.
#include <stdio.h> #include <string.h> struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; /* function declaration */ void printBook( struct Books *book ); int main( ) { struct Books Book1; /* Declare Book1 of type Book */ struct Books Book2; /* Declare Book2 of type Book */ /* book 1 specification */ strcpy( Book1.title, "C Programming"); strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial"); Book1.book_id = 6495407; /* book 2 specification */ strcpy( Book2.title, "Telecom Billing"); strcpy( Book2.author, "Zara Ali"); strcpy( Book2.subject, "Telecom Billing Tutorial"); Book2.book_id = 6495700; /* print Book1 info by passing address of Book1 */ printBook( &Book1 ); /* print Book2 info by passing address of Book2 */ printBook( &Book2 ); return 0; } void printBook( struct Books *book ) { printf( "Book title : %s\n", book->title); printf( "Book author : %s\n", book->author); printf( "Book subject : %s\n", book->subject); printf( "Book book_id : %d\n", book->book_id); }
Когда приведенный выше код компилируется и выполняется, он дает следующий результат —
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
Битовые поля
Битовые поля позволяют упаковывать данные в структуру. Это особенно полезно, когда память или хранилище данных стоят дорого. Типичные примеры включают —
-
Упаковка нескольких объектов в машинное слово. например, 1-битные флаги могут быть сжаты.
-
Чтение внешних форматов файлов — могут быть прочитаны нестандартные форматы файлов, например, 9-разрядные целые числа.
Упаковка нескольких объектов в машинное слово. например, 1-битные флаги могут быть сжаты.
Чтение внешних форматов файлов — могут быть прочитаны нестандартные форматы файлов, например, 9-разрядные целые числа.
C позволяет нам сделать это в определении структуры, поместив: bit length после переменной. Например —
struct packed_struct { unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; unsigned int f4:1; unsigned int type:4; unsigned int my_int:9; } pack;
Здесь pack_struct содержит 6 членов: четыре 1-битных флага f1..f3, 4-битный тип и 9-битный my_int.
C автоматически упаковывает вышеуказанные битовые поля настолько компактно, насколько это возможно, при условии, что максимальная длина поля меньше или равна целочисленной длине слова компьютера. Если это не так, то некоторые компиляторы могут допускать перекрытие памяти для полей, в то время как другие сохраняют следующее поле в следующем слове.