¿Por qué declarar una estructura que solo contiene una matriz en C?

131

Encontré un código que contiene lo siguiente:

struct ABC {
    unsigned long array[MAX];
} abc;

¿Cuándo tiene sentido usar una declaración como esta?

Joe.Z
fuente

Respuestas:

184

Le permite pasar la matriz a una función por valor, u obtenerla devuelta por valor de una función.

Las estructuras se pueden pasar por valor, a diferencia de las matrices que decaen a un puntero en estos contextos.

Blagovest Buyukliev
fuente
1
Tenga cuidado de hacer esto con matrices, más de 16 o 32 bytes, para funciones que no están en línea: es más eficiente pasarlas por referencia constante, a menos que la persona que llama ya necesite una copia tmp que pueda destruir. Si la llamada / devolución no se optimiza, una matriz mediana a grande (miles de bytes) es algo terrible para pasar por valor.
Peter Cordes
85

Otra ventaja es que abstrae el tamaño para que no tenga que usar [MAX]todo su código donde quiera que declare dicho objeto. Esto también podría lograrse con

typedef char ABC[MAX];

pero entonces tienes un problema mucho más grande: debes tener en cuenta que ABCes un tipo de matriz (aunque no puedas ver esto cuando declaras variables de tipo ABC) o de lo contrario te picará el hecho de que ABCsignificará algo diferente en una lista de argumentos de función versus en una declaración / definición de variable.

Una ventaja más es que la estructura le permite agregar más elementos si es necesario, sin tener que volver a escribir mucho código.

R .. GitHub DEJA DE AYUDAR AL HIELO
fuente
45

Puede copiar una estructura y devolver una estructura desde una función.

No puede hacer eso con una matriz, ¡a menos que sea parte de una estructura!

Bo Persson
fuente
26

Puedes copiarlo así.

struct ABC a, b;
........
a = b;

Para una matriz, necesitaría usar la función memcpy o un bucle para asignar cada elemento.

MetallicPriest
fuente
66
(por lo que permite un código más limpio, no hará ninguna diferencia en la velocidad, etc.)
John Carter
3
Eso es útil Desafortunadamente, no puedes hacerlo si (a == b)!?! qué inconsistente es eso. Para C ++ busca un operador ==. En C dice "operandos no válidos para binario ==".
Matt
11

Puede usar struct para crear un nuevo tipo de datos como una cadena . puedes definir:

struct String {
    char Char[MAX];
};

o puede crear una Lista de datos que puede usar por argumento de funciones o devolverla en sus métodos. La estructura es más flexible que una matriz, porque puede admitir algunos operadores como = y puede definir algunos métodos en ella.

Espero que sea útil para ti :)

Hossein Mobasher
fuente
2
Básicamente, es lo más cercano que C tiene para crear una clase. Me gusta esta respuesta porque se acerca más a señalar eso.
Nate CK
1
No existe un método en C. structs en C son datos antiguos simples. Tiene un operador = soportado por defecto (que las otras respuestas muestran es la razón para hacer esto), pero esto es engañoso y se aplica principalmente a C ++, no C.
Jonathan Sternberg
3
@J Sternberg: "Método" es solo una forma de pensar que las subrutinas están relacionadas con los "objetos" de datos que afectan. Ciertamente puede crear "clases" de "objetos" y "métodos" que operan en ellos en C. El lenguaje simplemente no define formalmente tales cosas. Si quieres crear mejores abstracciones en C, meter las cosas en una estructura suele ser la mejor manera de hacerlo.
Nate CK
Además, si realmente quisiera "crear" métodos en C, podría usar punteros de función (sí, sí, sintaxis complicada, sin protección de datos, etc.) para asociar funciones con los datos con los que operan. Tienes que pasar "self" en el primer argumento (incluso podrías llamarlo "this", si lo deseas), ya que no hay una creación automática de este puntero dentro de la función en C. Por supuesto, todo es gimnasia, obtienes cosas como esta por defecto en C ++, aunque es cierto que podría haber una sobrecarga oculta como un bono ...
BenPen 12/12/18
2

Otra ventaja de usar tal structes que hace cumplir la seguridad de tipo dondequiera que structse use; especialmente si tiene dos tipos que consisten en matrices del mismo tamaño utilizadas para diferentes propósitos, estos tipos lo ayudarán a evitar el uso accidental de una matriz de manera inapropiada.

Si no ajusta una matriz en a struct, aún puede declarar un typedefpara ello: esto tiene algunas de las ventajas de struct: • el tipo se declara una vez, • el tamaño es automáticamente correcto, • la intención del código se vuelve más clara, • y el código es más fácil de mantener, pero pierde ◦ seguridad de tipo estricta, ◦ la capacidad de copiar y devolver valores del tipo y ◦ la capacidad de agregar miembros más tarde sin romper el resto de su código. Dos typedefs para matrices desnudas de un tipo dado solo producen diferentes tipos si son de diferentes tamaños. Además, si usa el typedefsin *en un argumento de función, es equivalente a char *reducir drásticamente la seguridad de tipos.

En resumen :

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
PJTraill
fuente
1

Una estructura puede contener funciones de inicialización de matriz, copia y fini que emulan algunas de las ventajas de los paradigmas de administración de memoria OOP. De hecho, es muy fácil ampliar este concepto para escribir una utilidad de administración de memoria genérica (mediante el uso de la estructura sizeof () para saber exactamente cuántos bytes se administran) para administrar cualquier estructura definida por el usuario. Muchas de las bases de códigos de producción inteligentes escritas en C las usan mucho y, por lo general, nunca usan una matriz a menos que su alcance sea muy local.

De hecho, para una matriz incrustada en una estructura, puede hacer otras "cosas inteligentes", como la comprobación de límites en cualquier momento que desee acceder a esta matriz. Nuevamente, a menos que el alcance de la matriz sea muy limitado, es una mala idea usarlo y transmitir información a través de los programas. Tarde o temprano, te encontrarás con errores que te mantendrán despierto por las noches y arruinarán tus fines de semana.

Aniket
fuente
Esto no responde a la pregunta de por qué uno podría usar un que structcontenga solo una matriz.
PJTraill