Определение структур
Структура в языке программирования Си представляет собой производный тип данных, который объединяет в единое целое множество компонентов. При этом в отличие от массива эти компоненты могут представлять различные типы данных.
Для определения структуры применяется ключевое слово struct, а сам формат определения выглядит следующим образом:
1
2
3
4
struct имя_структуры
{
компоненты_структуры
};
Имя_структуры представляет произвольный идентификатор, к которому применяются те же правила, что и при наименовании переменных.
После имени структуры в фигурных скобках помещаются Компоненты_структуры, которые представляют набор описаний объектов, которые составляют структуру.
Следует отметить, что в отличие от функции при определении структуры после закрывающей фигурной скобки идет точка с запятой.
Например, определим простейшую структуру:
1
2
3
4
5
struct person
{
int age;
char * name;
};
Здесь определена структура person, которая имеет два элемента: age (представляет тип int) и name (представляет указатель на тип char).
Все элементы структуры объявляются как обычные переменные. Но в отличие от переменных при определении элементов структуры для них не выделяется память, и их нельзя инициализировать. По сути мы просто определяем новый тип данных.
После определения структуры мы можем ее использовать. Для начала мы можем определить объект структуры - по сути обычную переменную, которая будет представлять выше созданный тип:
1
struct person tom;
Здесь определена переменная tom, которая представляет структуру person. И при каждом определении переменной типа структуры ей будет выделяться память, необходимая для хранения ее элементов.
При определении переменной структуры ее можно сразу инициализировать, присвоив какое-нибудь значение:
1
struct person tom = {23, "Tom"};
Инициализация структур аналогична инициализации массивов: в фигурных скобках передаются значения для элементов структуры по порядку. Так как в структуре person первым определено свойство, которое представляет тип int - число, то в фигурных скобках вначале идет число. И так далее для всех элементов структуры по порядку.
Также после создания переменной структуры можно обращаться к ее элементам - получать их значения или, наоборот, присваивать им новые значения. Для обращения к элементам структуры используется операция "точка":
1
имя_переменной_структуры.имя_элемента
Теперь объединим все вместе в рамках программы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
struct person
{
int age;
char * name;
};
int main(void)
{
struct person tom = {23, "Tom"};
printf("Age: %d \t Name: %s", tom.age, tom.name);
return 0;
}
Консольный вывод программы:
Age: 23 Name: Tom
С элементами структуры можно производить все те же операции, что и с переменными тех же типов. Например, добавим ввод с консоли:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
struct person
{
int age;
char name[20];
};
int main(void)
{
struct person tom = {23, "Tom"};
printf("Enter name: ");
scanf("%s", &tom.name);
printf("Enter age: ");
scanf("%d", &tom.age);
printf("Name:%s \t Age: %d", tom.name, tom.age);
return 0;
}
Консольный вывод программы:
Enter name: Eugene
Enter age: 33
Name: Eugene Age: 33
Мы можем одновременно совмещать определение типа структуры и ее переменных:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
struct person
{
int age;
char * name;
} tom, bob, alice;
int main(void)
{
tom.name ="Tom";
tom.age = 23;
bob.name ="Bob";
bob.age = 15;
alice.name = "Alice";
alice.age=25;
printf("Name:%s \t Age: %d", tom.name, tom.age);
return 0;
}
После определения структуры, но до точки запятой мы можем через запятую перечислить набор переменных. А затем присвоить их элементам значения.
При подобном определении мы можем даже не указывать имя структуры:
1
2
3
4
5
struct
{
int age;
char * name;
} tom, bob, alice;
В этом случае компилятор все равно будет знать, что переменные tom, bob и alice представляют структуры с двумя элементами name и age. И соответственно мы также с этими переменными сможем работать. Другое дело, что мы не сможем задать новые переменные этой структуры в других местах программы.
typedef
Еще один способ определения структуры представляет ключевое слово typedef:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
typedef struct
{
int age;
char * name;
} person;
int main(void)
{
person tom = {23, "Tom"};
printf("Name:%s \t Age: %d", tom.name, tom.age);
return 0;
}
В конце определения структуры после закрывающей фигурной скобки идет ее обозначение - в данном случае person. В дальнейшем мы можем использовать это обозначение для создания переменной структуры. При этом в отличие от примеров выше здесь не надо при определении переменной не надо использовать слово struct.
Директива define
Еще один способ определить структуру представляет применение препроцессорной директивы #define:
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#define PERSON struct {int age; char name[20];}
int main(void)
{
PERSON tom = {23, "Tom"};
printf("Name:%s \t Age: %d", tom.name, tom.age);
return 0;
}
В данном случае директива define определяет константу PERSON, вместо которой при обработке исходного кода препроцессором будет вставляться код структуры struct {int age; char name[20];}