Perché dichiarare uno struct che contiene solo un array in C?


131

Mi sono imbattuto in alcuni codici contenenti quanto segue:

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

Quando ha senso usare una dichiarazione come questa?

Risposte:


184

Consente di passare l'array a una funzione in base al valore o di restituirlo in base al valore da una funzione.

Le strutture possono essere passate per valore, diversamente dalle matrici che decadono in un puntatore in questi contesti.


1
Fai attenzione a farlo con le matrici, più di 16 o 32 byte, per funzioni che non sono in linea: è più efficiente passarle per riferimento costante, a meno che la chiamata non abbia già bisogno di una copia tmp che può distruggere. Se la chiamata / il ritorno non si ottimizzano, un array medio-grande (migliaia di byte) è una cosa terribile da passare per valore.
Peter Cordes,

85

Un altro vantaggio è che estrae la dimensione in modo da non dover usare [MAX]tutto il codice ovunque tu dichiari un oggetto del genere. Questo potrebbe anche essere raggiunto con

typedef char ABC[MAX];

ma poi hai un problema molto più grande: devi essere consapevole che ABCè un tipo di array (anche se non puoi vederlo quando dichiari variabili di tipo ABC) oppure rimarrai colpito dal fatto che ABCsignificherà qualcosa di diverso in un elenco di argomenti di funzioni rispetto a una dichiarazione / definizione variabile.

Un altro vantaggio è che la struttura ti consente di aggiungere più elementi in seguito, se necessario, senza dover riscrivere un sacco di codice.


45

È possibile copiare una struttura e restituire una struttura da una funzione.

Non puoi farlo con un array - a meno che non faccia parte di uno struct!


26

Puoi copiarlo in questo modo.

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

Per un array è necessario utilizzare la funzione memcpy o un loop per assegnare ciascun elemento.


6
(quindi consente un codice più pulito - non farà alcuna differenza di velocità, ecc.)
John Carter,

3
Questo è utile Sfortunatamente non puoi fare se (a == b)!?! quanto è incoerente. Per C ++ cerca un operatore ==. In C dice "operandi non validi in binario ==".
Matt,

11

Puoi usare struct per creare un nuovo tipo di dati come stringa . puoi definire:

struct String {
    char Char[MAX];
};

oppure puoi creare un Elenco di dati che puoi utilizzare per argomento di funzioni o restituirlo nei tuoi metodi. La struttura è più flessibile di un array, perché può supportare alcuni operatori come = e in esso è possibile definire alcuni metodi.

Spero sia utile per te :)


2
Fondamentalmente, è la cosa più vicina a C per creare una classe. Mi piace questa risposta perché è la più vicina a segnalarla.
Nate CK,

1
Non esiste un metodo in C. le strutture in C sono semplici vecchi dati. Ha un = operatore supportato di default (che le altre risposte mostrano è il motivo per farlo), ma questo è fuorviante e si applica principalmente al C ++, non a C.
Jonathan Sternberg

3
@J Sternberg: "Metodo" è solo un modo di pensare alle subroutine come correlate agli "oggetti" di dati che influenzano. Puoi certamente creare "classi" di "oggetti" e "metodi" che operano su di essi in C. Il linguaggio semplicemente non definisce formalmente tali cose. Se vuoi creare astrazioni migliori in C, inserire le cose in una struttura è di solito il modo migliore per farlo.
Nate CK,

Inoltre, se si desidera veramente "creare" metodi in C, è possibile utilizzare i puntatori a funzione (sì, sì, sintassi complicata, nessuna protezione dei dati, ecc.) Per associare le funzioni ai dati su cui operano. Devi passare in "sé" nel primo argomento (potresti anche chiamarlo "questo", se lo desideri), dal momento che non esiste una creazione automatica di questo puntatore all'interno della funzione in C. Ovviamente, è tutta la ginnastica, ottieni cose come questa di default in C ++, anche se è vero che potrebbe esserci un overhead nascosto come bonus ...
BenPen

2

Un altro vantaggio dell'uso di un tale structè che applica la sicurezza del tipo ovunque structvenga usato; specialmente se hai due tipi costituiti da array della stessa dimensione usati per scopi diversi, questi tipi ti aiuteranno a evitare di usare involontariamente un array in modo inappropriato.

Se non si avvolge un array in a struct, è comunque possibile dichiarare a typedefper esso: questo presenta alcuni dei vantaggi del struct- • il tipo viene dichiarato una volta, • la dimensione è automaticamente corretta, • l'intento del codice diventa più chiaro, • e il codice è più gestibile, ma si perde ◦ rigorosa sicurezza del tipo, ◦ la capacità di copiare e restituire valori del tipo e ability la possibilità di aggiungere membri in un secondo momento senza interrompere il resto del codice. Due typedefs per array nudi di un determinato tipo producono tipi diversi solo se di dimensioni diverse. Inoltre, se si utilizza il typedefsenza *in un argomento della funzione, equivale a char *ridurre drasticamente la sicurezza del tipo.

In sintesi :

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

1

Una struttura può contenere funzioni di inizializzazione, copia e fini dell'array che emulano alcuni dei vantaggi dei paradigmi di gestione della memoria OOP. In effetti, è molto facile estendere questo concetto per scrivere un'utilità di gestione della memoria generica (usando la struttura sizeof () per sapere esattamente quanti byte vengono gestiti) per gestire qualsiasi struttura definita dall'utente. Molte delle basi di codici di produzione intelligenti scritte in C usano queste in modo pesante e in genere non usano mai un array a meno che il suo ambito non sia molto locale.

In effetti, per un array incorporato in una struttura, è possibile fare altre "cose ​​intelligenti" come il controllo associato ogni volta che si desidera accedere a questo array. Ancora una volta, a meno che l'ambito dell'array non sia molto limitato, è una cattiva idea usarlo e passare informazioni tra i programmi. Prima o poi, ti imbatterai in bug che ti terranno sveglio di notte e rovineranno i tuoi fine settimana.


Questo non risponde alla domanda sul perché si potrebbe usare un structcontenente solo un array.
PJTraill
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.