Структуры

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

Последнее обновление: 06.01.2023

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

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

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

struct имя_структуры
{
	компоненты_структуры
};

Имя_структуры представляет произвольный идентификатор, к которому применяются те же правила, что и при наименовании переменных.

После имени структуры в фигурных скобках помещаются компоненты структуры - объекты, которые составляют структуру.

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

Например, определим простейшую структуру:

struct person
{
	int age;
	char * name;
};

Здесь определена структура person, которая имеет два элемента: age (представляет тип int) и name (представляет указатель на тип char).

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

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

После определения структуры мы можем ее использовать. Для начала мы можем определить объект структуры - по сути обычную переменную, которая будет представлять выше созданный тип:

// определение структуры person
struct person
{
    int age;
    char * name;
};

int main(void)
{
    // определение переменной, которая представляет структуру person
    struct person tom;
}

Здесь определена переменная tom, которая представляет структуру person. И при каждом определении переменной типа структуры ей будет выделяться память, необходимая для хранения ее элементов.

Инициализация структуры

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

  • По позиции: значения передаются элементам структуры в том порядке, в котором они следуют в структуре:

    struct person tom = {23, "Tom"};

    Так как в структуре person первым определено свойство age, которое представляет тип int - число, то в фигурных скобках вначале идет число, которое передается элементу age. Вторым идет элемент name, который представляет указатель на тип char или строку, соответственно вторым идет строка. И так далее для всех элементов структуры по порядку.

  • По имени: значения передаются элементам структуры по имени, независимо от порядка:

    struct person tom = {.name="Tom", .age=23};

    В этом случае перед именем элемента указывается точка, например, .name.

Обращение к элементам структуры

Также после создания переменной структуры можно обращаться к ее элементам - получать их значения или, наоборот, присваивать им новые значения. Для обращения к элементам структуры используется операция "точка":

имя_переменной_структуры.имя_элемента

Теперь объединим все вместе в рамках программы:

#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

Можно инициализировать элементы структуры по отдельности:

#include <stdio.h>
 
struct person
{
    int age;
    char * name;
};
 
int main(void)
{
    struct person tom;
    tom.name ="Tom";
    tom.age = 22;
    printf("Name:%s \t Age: %d", tom.name, tom.age);
    return 0;
}

Объединение определение структуры и ее переменных.

Мы можем одновременно совмещать определение типа структуры и ее переменных:

#include <stdio.h>

struct person
{
	int age;
	char * name;
} tom;		// определение структуры и ее переменной

int main(void)
{
	tom = {38, "Tom"};
	printf("Name:%s \t Age: %d", tom.name, tom.age);
	return 0;
}

После определения структуры, но до точки с запятой мы можем указать переменные этой структуры. А затем присвоить их элементам значения.

Можно тут же инициализировать структуру:

#include <stdio.h>
 
struct person
{
    int age;
    char * name;
} tom = {38, "Tom"};
 
int main(void)
{
    printf("Name:%s \t Age: %d", tom.name, tom.age);
    return 0;
}

Можно определить сразу несколько переменных:

struct person
{
    int age;
    char * name;
} tom, bob, alice;

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

struct
{
	int age;
	char * name;
} tom;

В этом случае компилятор все равно будет знать, что переменная tom представляет структуры с двумя элементами name и age. И соответственно мы также с этими переменными сможем работать. Другое дело, что мы не сможем задать новые переменные этой структуры в других местах программы.

typedef

Еще один способ определения структуры представляет ключевое слово typedef:

#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:

#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];}

Копирование структур

Одну структуру можно присвавивать другой структуре того же типа. При копировании элементы структуры получают копии значений:

#include <stdio.h>
 
struct person
{
    int age;
    char * name;
};
 
int main(void)
{
    struct person tom = {38, "Tom"};
    // копируем значения из структуры tom в структуру bob
    struct person bob = tom;
    bob.name = "Bob";
    printf("Name: %s \t Age: %d \n", bob.name, bob.age);
    printf("Name: %s \t Age: %d \n", tom.name, tom.age);
    return 0;
}

Здесь в переменную bob копируются данные из структуры tom. Далее мы для структуры bob меняется значение поля name. В итоге мы получим следующий консольный вывод:

Name: Bob         Age: 38
Name: Tom         Age: 38

Ввод с консоли данных для структуры

С элементами структуры можно производить все те же операции, что и с переменными тех же типов. Например, добавим ввод с консоли:

#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
Дополнительные материалы
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850