Зачем объявлять структуру, которая содержит только массив в C?
Я наткнулся на некоторый код, содержащий следующее:
struct ABC {
unsigned long array[MAX];
} abc;
Когда имеет смысл использовать такое объявление?
7 ответов
Он позволяет передавать массив функции по значению или возвращать его по значению из функции.
Структуры могут передаваться по значению, в отличие от массивов, которые затухают до указателя в этих контекстах.
Еще одним преимуществом является то, что он абстрагируется от размера, поэтому вам не нужно использовать [MAX]
во всем вашем коде, где бы вы ни объявили такой объект. Это также может быть достигнуто с
typedef char ABC[MAX];
но тогда у вас есть гораздо большая проблема: вы должны знать, что ABC
это тип массива (даже если вы не видите этого, когда объявляете переменные типа ABC
) или иначе вы будете ужалены тем фактом, что ABC
будет означать что-то другое в списке аргументов функции и в объявлении / определении переменной.
Еще одним преимуществом является то, что структура позволяет позже добавлять больше элементов, если вам нужно, без необходимости переписывать много кода.
Вы можете скопировать структуру и вернуть структуру из функции.
Вы не можете сделать это с массивом - если он не является частью структуры!
Вы можете скопировать это так.
struct ABC a, b;
........
a = b;
Для массива вам нужно использовать функцию memcpy или цикл для назначения каждого элемента.
Вы можете использовать struct для создания нового типа данных, таких как строка. Вы можете определить:
struct String {
char Char[MAX];
};
или вы можете создать список данных, который вы можете использовать по аргументу функций или вернуть его в ваши методы. Структура является более гибкой, чем массив, потому что она может поддерживать некоторые операторы, такие как =, и вы можете определить некоторые методы в ней.
Надеюсь, это полезно для вас:)
Еще одно преимущество использования такого struct
является то, что он обеспечивает безопасность типов везде, где такие struct
используется; особенно если у вас есть два типа, состоящие из массивов одного размера, используемых для разных целей, эти типы помогут вам избежать случайного использования массива ненадлежащим образом.
Если вы не оборачиваете массив в struct
, вы все еще можете объявить typedef
для этого: у этого есть некоторые из преимуществ struct
- • тип объявляется один раз, • размер автоматически корректируется, • цель кода становится более понятной, • и код более удобен в обслуживании - но вы теряете ◦ строгую безопасность типов ◦ возможность копировать и возвращать значения типа и ◦ возможность добавлять участников позже, не нарушая остальную часть вашего кода. Два typedef
s для голых массивов данного типа дают разные типы, только если они имеют разные размеры. Более того, если вы используете typedef
без *
в аргументе функции это эквивалентно char *
, резко снижая безопасность типов.
В итоге:
typedef struct A_s_s { char m[113]; } A_s_t; // Full type safey, assignable
typedef char A_c_t[113]; // Partial type-safety, not assignable
A_s_t v_s(void); // Allowed
A_c_t v_c(void); // Forbidden
void s__v(A_s_t); // Type-safe, pass by value
void sP_v(A_s_t *); // Type-safe
void c__v(A_c_t); // UNSAFE, just means char * (GRRR!)
void cP_v(A_c_t *); // SEMI-safe, accepts any array of 113
Структура может содержать функции инициализации массива, копирования и завершения, имитирующие некоторые преимущества парадигм управления памятью ООП. Фактически, очень легко расширить эту концепцию, чтобы написать общую утилиту управления памятью (используя структуру sizeof(), чтобы точно знать, сколько байтов управляется) для управления любой определенной пользователем структурой. Многие из умных производственных кодовых баз, написанных на C, интенсивно используют их и, как правило, никогда не используют массив, если его область действия не очень локальна.
Фактически для массива, встроенного в структуру, вы могли бы делать другие "умные вещи", такие как проверка границ, в любое время, когда вы хотите получить доступ к этому массиву. Опять же, если область действия массива не очень ограничена, использовать его и передавать информацию между программами - плохая идея. Рано или поздно вы столкнетесь с ошибками, которые не дадут вам спать по ночам и испортят ваши выходные.