C Структура

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

Элементы данных в структуре могут быть базовыми типами данных (такими как int, float, char и т. д.), или другими типами структур, типами указателей и так далее.

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

  • Title
  • Автор
  • Тема
  • ID книги

Определение структуры

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

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

struct tag {
    member-list
    member-list
    member-list  
    ...
} variable-list ;

tag— это тег структуры.

member-list— это стандартное определение переменной, напримерint i;илиfloat f;, либо другие допустимые определения переменных.

variable-listПеременные структуры, определяемые в конце структуры, перед завершающей точкой с запятой; можно указать одну или несколько переменных структуры. Ниже показан способ объявления структуры Book:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;  

В общем,тег, список членов, список переменныхПо крайней мере 2 из этих 3 частей должны присутствовать. Ниже приведён пример:

// Это объявление объявляет структуру с 3 членами, а именно целое a, символ b и double c
// Оно также объявляет переменную структуры 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 B;    // Сделайте неполное объявление структуры B

// struct A содержит указатель на struct B
struct A
{
    struct B *partner;
    //другие члены;
};

// struct B содержит указатель на struct A; после объявления A также объявляется B.
struct B
{
    struct A *partner;
    //другие члены;
};

Инициализация переменных структур

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

Пример

#include <stdio.h>

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 <stdio.h>
#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 <stdio.h>
#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 <stdio.h>
#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Он возвращает общее количество байтов структуры, включая размеры всех переменных-членов и возможные байты заполнения.

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

Пример

#include <stdio.h>

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))атрибуты и так далее, чтобы дополнительно управлять размером и выравниванием структуры и запрашивать их.

Другие расширения