C Структура
Массивы C позволяют определять переменные, которые могут хранить элементы данных одного типа,Структураи являются еще одним определяемым пользователем типом данных, доступным в программировании на C, который позволяет хранить элементы данных разных типов.
Элементы данных в структуре могут быть базовыми типами данных (такими как int, float, char и т. д.), или другими типами структур, типами указателей и так далее.
Структуры используются для представления записи. Предположим, вы хотите отслеживать динамику книг в библиотеке; возможно, вам потребуется отслеживать следующие атрибуты для каждой книги:
- Title
- Автор
- Тема
- ID книги
Определение структуры
Определение структуры состоит из ключевого словаstructи имени структуры. Имя структуры можно задать по мере необходимости.
Оператор struct определяет новый тип данных, содержащий несколько членов. Формат оператора struct следующий:
member-list
member-list
member-list
...
} variable-list ;
tag— это тег структуры.
member-list— это стандартное определение переменной, напримерint i;илиfloat f;, либо другие допустимые определения переменных.
variable-listПеременные структуры, определяемые в конце структуры, перед завершающей точкой с запятой; можно указать одну или несколько переменных структуры. Ниже показан способ объявления структуры Book:
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
В общем,тег, список членов, список переменныхПо крайней мере 2 из этих 3 частей должны присутствовать. Ниже приведён пример:
// Оно также объявляет переменную структуры s1
// Эта структура не указывает свой тег
struct
{
int a;
char b;
double c;
} s1;
// Это объявление объявляет структуру с 3 членами, а именно целое a, символ b и double c
// Тег структуры называется SIMPLE, и ни одна переменная не объявлена
struct SIMPLE
{
int a;
char b;
double c;
};
// Используя структуру с тегом SIMPLE, объявляются дополнительные переменные t1, t2, t3
struct SIMPLE t1, t2[20], *t3;
// Вы также можете использовать typedef для создания нового типа
typedef struct
{
int a;
char b;
double c;
} Simple2;
// Теперь Simple2 можно использовать как тип для объявления новых переменных структуры
Simple2 u1, u2[20], *u3;
В приведённых выше объявлениях первое и второе объявления рассматриваются компилятором как два совершенно разных типа, даже если их списки членов совпадают. Если вы присвоите t3=&s1, это недопустимо.
Члены структуры могут содержать другие структуры, а также могут содержать указатели на собственный тип структуры. Обычно такие указатели используются для реализации более сложных структур данных, таких как связанные списки и деревья.
struct COMPLEX
{
char string[100];
struct SIMPLE a;
};
// Это объявление структуры содержит указатель на собственный тип
struct NODE
{
char string[100];
struct NODE *next_node;
};
Если две структуры содержат друг друга, одной из структур требуется неполное объявление, как показано ниже:
// struct A содержит указатель на struct B
struct A
{
struct B *partner;
//другие члены;
};
// struct B содержит указатель на struct A; после объявления A также объявляется B.
struct B
{
struct A *partner;
//другие члены;
};
Инициализация переменных структур
Как и переменные других типов, переменные структур могут получать начальные значения во время определения.
Пример
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book = {"C language", "EXAMPLE", "programming language", 123456};
int main()
{
printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}
Вывод после выполнения:
title : C 语言 author: EXAMPLE subject: 编程语言 book_id: 123456
Доступ к членам структуры
Чтобы получить доступ к членам структуры, мы используемоператор доступа к членам (.)Оператор доступа к членам — это точка между именем переменной структуры и членом структуры, к которому мы хотим получить доступ. Вы можете использоватьstructкак ключевое слово для определения переменных типа структуры. Следующий пример демонстрирует использование структур:
Пример
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
struct Books Book1; /* Объявить Book1 типа Books */
struct Books Book2; /* Объявить Book2 типа Books */
/* Детали Book1 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Детали Book2 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* Вывод информации о Book1 */
printf( "Название книги 1 : %s\n", Book1.title);
printf( "Автор книги 1 : %s\n", Book1.author);
printf( "Тема книги 1 : %s\n", Book1.subject);
printf( "Идентификатор книги 1 : %d\n", Book1.book_id);
/* Вывод информации о Book2 */
printf( "Название книги 2 : %s\n", Book2.title);
printf( "Автор книги 2 : %s\n", Book2.author);
printf( "Тема книги 2 : %s\n", Book2.subject);
printf( "Идентификатор книги 2 : %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 <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* Объявление функции */
void printBook( struct Books book );
int main( )
{
struct Books Book1; /* Объявить Book1 типа Books */
struct Books Book2; /* Объявить Book2 типа Books */
/* Детали Book1 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Детали Book2 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* Вывод информации о Book1 */
printBook( Book1 );
/* Вывод информации о 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
Указатель на структуру
Вы можете определить указатель на структуру способом, аналогичным определению указателей на переменные других типов, как показано ниже:
struct Books *struct_pointer;
Теперь вы можете сохранить адрес переменной структуры в переменной-указателе, определённой выше. Чтобы найти адрес переменной структуры, поставьте оператор & перед именем структуры, как показано ниже:
struct_pointer = &Book1;
Чтобы получить доступ к членам структуры с помощью указателя на структуру, вы должны использовать оператор ->, как показано ниже:
struct_pointer->title;
Давайте перепишем приведённый выше пример, используя указатели на структуры, что поможет вам понять концепцию указателей на структуры:
Пример
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* Объявление функции */
void printBook( struct Books *book );
int main( )
{
struct Books Book1; /* Объявить Book1 типа Books */
struct Books Book2; /* Объявить Book2 типа Books */
/* Детали Book1 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Детали Book2 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* Вывод информации о Book1 путем передачи адреса Book1 */
printBook( &Book1 );
/* Вывод информации о Book2 путем передачи адреса 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
Вычисление размера структуры
В языке C мы можем использоватьsizeofоператор для вычисления размера структуры,sizeofОн возвращает размер в байтах для заданного типа или переменной.
Для структур,sizeofОн возвращает общее количество байтов структуры, включая размеры всех переменных-членов и возможные байты заполнения.
В следующем примере показано, как вычислить размер структуры:
Пример
struct Person {
char name[20];
int age;
float height;
};
int main() {
struct Person person;
printf("Size of struct Person: %zu bytes\n", sizeof(person));
return 0;
}
В приведенном выше примере мы определили структуру с именемPersonСтруктура, содержащая массив символовname, целое числоageи число с плавающей точкойheight。
Вmain-функции мы объявилиPersonпеременную типаperson, затем используйтеsizeofоператор, чтобы получитьpersonразмер структуры.
Наконец, мы используемprintfФункция выводит размер структуры, и вывод выглядит следующим образом:
结构体 Person 大小为: 28 字节
Примечание: размер структуры может зависеть от правил оптимизации и выравнивания компилятора. Компилятор может вставлять дополнительные байты заполнения в структуру, чтобы выровнять переменные-члены структуры, повышая эффективность доступа к памяти. Поэтому фактический размер структуры может быть больше суммы размеров переменных-членов. Если вам нужно точно знать расположение в памяти и выравнивание структуры, вы можете использоватьoffsetofмакрос и__attribute__((packed))атрибуты и так далее, чтобы дополнительно управлять размером и выравниванием структуры и запрашивать их.
Другие расширения