Warum eine Struktur deklarieren, die nur ein Array in C enthält?


131

Ich bin auf einen Code gestoßen, der Folgendes enthält:

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

Wann ist es sinnvoll, eine solche Erklärung zu verwenden?

Antworten:


184

Sie können das Array als Wert an eine Funktion übergeben oder von einer Funktion als Wert zurückgeben.

Strukturen können im Gegensatz zu Arrays, die in diesen Kontexten zu einem Zeiger zerfallen, als Wert übergeben werden.


1
Hüten Sie sich davor, dies mit Arrays zu tun, die mehr als 16 oder 32 Bytes enthalten, für Funktionen, die nicht inline sind: Es ist effizienter, sie als const-Referenz zu übergeben, es sei denn, der Angerufene benötigt bereits eine tmp-Kopie, die er zerstören kann. Wenn der Aufruf / die Rückgabe nicht optimiert wird, ist es eine schreckliche Sache, ein mittleres bis großes Array (Tausende von Bytes) als Wert zu übergeben.
Peter Cordes

84

Ein weiterer Vorteil ist, dass die Größe abstrahiert wird, sodass Sie nicht den [MAX]gesamten Code verwenden müssen, wo immer Sie ein solches Objekt deklarieren. Dies könnte auch mit erreicht werden

typedef char ABC[MAX];

Aber dann haben Sie ein viel größeres Problem: Sie müssen sich bewusst sein, dass ABCes sich um einen Array-Typ handelt (obwohl Sie dies nicht sehen können, wenn Sie Variablen vom Typ deklarieren ABC), sonst werden Sie von der Tatsache gestochen, dass ABCdies etwas anderes bedeutet in einer Funktionsargumentliste versus in einer Variablendeklaration / -definition.

Ein weiterer Vorteil ist, dass Sie mit der Struktur später bei Bedarf weitere Elemente hinzufügen können, ohne viel Code neu schreiben zu müssen.


45

Sie können eine Struktur kopieren und eine Struktur von einer Funktion zurückgeben.

Sie können dies nicht mit einem Array tun - es sei denn, es ist Teil einer Struktur!


26

Sie können es so kopieren.

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

Für ein Array müssten Sie die memcpy- Funktion oder eine Schleife verwenden, um jedes Element zuzuweisen.


6
(so erlaubt es saubereren Code - es wird keinen Unterschied in der Geschwindigkeit usw. machen)
John Carter

3
Das ist nützlich. Das kannst du leider nicht wenn (a == b)!?! wie inkonsistent das ist. Für C ++ sucht es nach einem == Operator. In C heißt es "ungültige Operanden zu binär ==".
Matt

11

Sie können struct verwenden, um einen neuen Datentyp wie string zu erstellen . Sie können definieren:

struct String {
    char Char[MAX];
};

oder Sie können eine Liste von Daten erstellen , die Sie anhand von Funktionsargumenten verwenden oder in Ihren Methoden zurückgeben können. Die Struktur ist flexibler als ein Array, da sie einige Operatoren wie = unterstützen kann und Sie darin einige Methoden definieren können.

Hoffe es ist nützlich für dich :)


2
Grundsätzlich ist es das Nächste, was C zum Erstellen einer Klasse hat. Ich mag diese Antwort, weil sie dem Hinweis am nächsten kommt.
Nate CK

1
Keine Methode in C. Strukturen in C sind einfache alte Daten. Es hat einen Operator =, der standardmäßig unterstützt wird (was die anderen Antworten zeigen, ist der Grund dafür), aber dies ist irreführend und gilt hauptsächlich für C ++, nicht für C.
Jonathan Sternberg

3
@J Sternberg: "Methode" ist nur eine Art, Subroutinen als mit den Daten "Objekten" verwandt zu betrachten, die sie betreffen. Sie können sicherlich "Klassen" von "Objekten" und "Methoden" erstellen, die in C auf sie einwirken. Die Sprache definiert solche Dinge einfach nicht formal. Wenn Sie in C bessere Abstraktionen erstellen möchten, ist es normalerweise am besten, Dinge in eine Struktur zu stopfen.
Nate CK

Wenn Sie wirklich Methoden in C "erstellen" möchten, können Sie Funktionszeiger (Ja, Ja, knifflige Syntax, kein Datenschutz usw.) verwenden, um Funktionen mit den Daten zu verknüpfen, mit denen sie arbeiten. Sie müssen im ersten Argument "self" übergeben (Sie können es sogar "this" nennen, wenn Sie möchten), da dieser Zeiger in der Funktion in C nicht automatisch erstellt wird. Natürlich ist alles Gymnastik Dinge wie diese standardmäßig in C ++, obwohl es wahr ist, dass Overhead als Bonus versteckt sein könnte ...
BenPen

2

Ein weiterer Vorteil der Verwendung eines solchen structist, dass es die Typensicherheit überall dort erzwingt, wo ein solches structverwendet wird; Insbesondere wenn Sie zwei Typen haben, die aus Arrays gleicher Größe bestehen, die für unterschiedliche Zwecke verwendet werden, können Sie mit diesen Typen vermeiden, dass ein Array versehentlich unangemessen verwendet wird.

Wenn Sie ein Array nicht in a structeinschließen, können Sie dennoch ein deklarieren typedef: Dies hat einige der Vorteile von struct: • Der Typ wird einmal deklariert, • Die Größe wird automatisch korrigiert, • Die Absicht des Codes wird klarer, • und Code ist wartbarer - aber Sie verlieren ◦ strenge Typensicherheit, ◦ die Fähigkeit, Werte des Typs zu kopieren und zurückzugeben und ◦ die Fähigkeit, später Mitglieder hinzuzufügen, ohne den Rest Ihres Codes zu beschädigen. Zwei typedefs für bloße Arrays eines bestimmten Typs ergeben nur dann unterschiedliche Typen, wenn sie unterschiedliche Größen haben. Wenn Sie außerdem das Argument typedefwithout *in einem Funktionsargument verwenden, entspricht dies einer char *drastischen Reduzierung der Typensicherheit.

Zusammenfassend :

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

Eine Struktur kann Array-Initialisierungs-, Kopier- und Fini-Funktionen enthalten, die einige der Vorteile der OOP-Speicherverwaltungsparadigmen emulieren. Tatsächlich ist es sehr einfach, dieses Konzept zu erweitern, um ein generisches Dienstprogramm zur Speicherverwaltung zu schreiben (indem Sie die Struktur sizeof () verwenden, um genau zu wissen, wie viele Bytes verwaltet werden), um eine benutzerdefinierte Struktur zu verwalten. Viele der in C geschriebenen intelligenten Produktionscodebasen verwenden diese häufig und verwenden normalerweise nie ein Array, es sei denn, sein Umfang ist sehr lokal.

Tatsächlich können Sie für ein in eine Struktur eingebettetes Array andere "intelligente Dinge" ausführen, z. B. die gebundene Überprüfung, wann immer Sie auf dieses Array zugreifen möchten. Auch hier ist es eine schlechte Idee, ihn zu verwenden und Informationen programmübergreifend weiterzugeben, es sei denn, der Array-Bereich ist sehr begrenzt. Früher oder später werden Sie auf Fehler stoßen, die Sie nachts wach halten und Ihre Wochenenden ruinieren.


Dies beantwortet nicht die Frage, warum man ein Array verwenden könnte, structdas nur ein Array enthält.
PJTraill
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.