Массивы структур — один из популярных способов хранения и обработки однотипных данных в языке C, вроде таблицы данных, массива точек, сотрудников и др.
История вопроса:
Поддержка массивов и структур появилась в первых версиях C для удобства организации данных. Однако работа с массивами структур требует понимания особенностей языка, работы с памятью и принципов передачи данных.
Проблема:
Ошибка возникает при неправильной инициализации массива структур, путанице с памятью, передаче массива в функцию (может быть передан как указатель), а также при ошибках доступа к полям структур через неправильное индексирование.
Решение:
. и ->.Пример кода:
#include <stdio.h> struct Point { int x; int y; }; void print_points(struct Point *arr, int size) { for(int i = 0; i < size; ++i) { printf("(%d, %d) ", arr[i].x, arr[i].y); } } int main() { struct Point points[3] = { {1,2}, {3,4}, {5,6} }; print_points(points, 3); return 0; }
Ключевые особенности:
Чем отличается доступ к полям структуры в массиве через точку и стрелку?
arr[i].field используется, если arr[i] — это сама структура.
ptr->field используется, если ptr — указатель на структуру.
struct Point *p = &points[0]; printf("%d", p->x); // корректно // points[0].x — тоже корректно
Если частичная инициализация массива структур — какие значения будут у остальных полей?
При частичной инициализации неуказанные поля заполняются нулями в статически аллоцированных массивах, но не для автоматических (стековых) переменных без инициализации.
struct Point arr[2] = { {10} }; // arr[0].x = 10, arr[0].y = 0, arr[1].x и arr[1].y = 0
Передаются ли при передаче массива структур в функцию копии структур?
Нет, передается указатель на первый элемент массива, при этом функция может изменять элемент(ы), так как работает с оригинальной памятью.
Программист объявил массив структур, не инициализируя поля, и передал его в функцию для заполнения. Использовал оператор . вместо -> при работе с указателем. В результате получилась ошибка типа и использование мусорных значений.
Плюсы:
Минусы:
Был использован явный нулевой инициализатор {0} для всего массива, функция принимала указатель и размер, доступ к полям ввёден строго и согласно типу (arr[i].x).
Плюсы:
Минусы: