Was ist das Besondere an Strukturen?

81

Ich weiß, dass wir in C kein Array von einer Funktion zurückgeben können, sondern einen Zeiger auf ein Array. Aber ich möchte wissen, was das Besondere daran ist structs, dass sie von Funktionen zurückgegeben werden können, obwohl sie möglicherweise Arrays enthalten.

Warum macht das structWrapping das folgende Programm gültig?

#include <stdio.h>

struct data {
    char buf[256];
};

struct data Foo(const char *buf);

int main(void)
{
    struct data obj;
    obj = Foo("This is a sentence.");
    printf("%s\n", obj.buf);
    return 0;
}

struct data Foo(const char *buf)
{
    struct data X;
    strcpy(X.buf, buf);
    return X;
}
Sourav Ghosh
quelle
1
Sie könnten das gleiche mit einem tun union. Was ist das Besondere an Gewerkschaften?
user253751
19
Sie sollten lieber fragen, warum Arrays in C so seltsam sind.
CodesInChaos
Wenn bei der Rückgabe einer Struktur die Struktur nicht in ein paar Register passt und dann ein vom Compiler zugewiesener 'versteckter' Speicher vorhanden ist, wird die Struktur (über memcpy ()) in den versteckten Speicher kopiert und dann erneut kopiert (über memcpy () )) für die Strukturvariable des Aufrufers. Dieser 'versteckte' Speicher geht für alle anderen Funktionen verloren. Die zwei zusätzlichen Aufrufe memcpy()und der Verlust des 'versteckten' Speichers sind der Hauptgrund dafür, dass eine Struktur passed toweder returned fromeine Funktion noch eine Funktion sein sollte. Am besten übergeben Sie einen Zeiger auf die Struktur.
user3629249
Keine der drei Antworten befasst sich mit der Übergabe einer Struktur (sie diskutieren nur die Übergabe von Arrays), aber sie beantworten die Frage nicht.
user3629249
1
@ user3629249 - Es ist unmöglich, die Frage zu beantworten, da die Frage auf einem Unverständnis beruht. Die einzige Möglichkeit, die Frage zu beantworten, besteht darin, zu erklären, warum die Frage nicht gestellt werden kann. Stellen Sie sich vor, ich hätte Sie gefragt: "Warum hat Blau die gleiche Farbe wie Rot?" Sie würden schnell erklären, warum Sie die Frage nicht beantworten können.
Hogan

Antworten:

100

Eine bessere Möglichkeit, dieselbe Frage zu stellen, wäre "Was ist das Besondere an Arrays?", Denn es sind die Arrays, denen eine spezielle Behandlung zugeordnet ist, nicht structs.

Das Verhalten beim Übergeben und Zurückgeben von Arrays per Zeiger geht auf die ursprüngliche Implementierung von C zurück. Arrays "zerfallen" in Zeiger, was zu großer Verwirrung führt, insbesondere bei Personen, die neu in der Sprache sind. Strukturen hingegen verhalten sich wie integrierte Typen wie ints, doubles usw. Dies schließt alle in die eingebetteten Arrays ein struct, mit Ausnahme von flexiblen Array-Elementen , die nicht kopiert werden.

dasblinkenlight
quelle
4
"viel Verwirrung stiften" in der Tat. 'x' und '& x', die den gleichen Wert / die gleiche Adresse haben, sind irgendwie verrückt. Es ist nicht überraschend, dass Neulinge die Indirektion falsch verstehen :(
Martin James
1
Mein Gedächtnis könnte mich betrügen, aber gab es nicht Zeiten, in denen structes nicht möglich war, s als Wert zu übergeben?
Alk
5
@alk Ich denke, als Strukturen zum ersten Mal zur Sprache hinzugefügt wurden, gab es anfangs einige Einschränkungen beim Übergeben an / Zurückgeben von Funktionen, aber diese wurden eindeutig als ein Mangel im Compiler markiert, der bald genug korrigiert wurde, kein Hinweis dass irgendetwas falsch daran war, sie passieren und zurückgeben zu wollen.
Steve Summit
8
@jamesqf : struct Point {short x, y, z;};. Sie möchten wirklich Zeiger verwenden, um sie zu verschieben? Auf diese Weise sparen Sie sicherlich keinen Platz.
Mark VY
6
@jamesqf Ich bin nicht sicher, ob dies eine Antwort verdient. Wenn Sie glauben, dass C nicht viel mehr als Assembly ist, wenn Sie glauben, dass es nie einen Grund gibt, keinen Zeiger zu verwenden, kann ich vielleicht sehen, wie Sie denken, dass das Übergeben von Strukturen nutzlos ist. Aber für den Rest von uns, die C als eine Sprache auf hoher Ebene behandeln (wenn auch eine Sprache auf niedriger Ebene, wie HLLs gehen) und die das Typsystem von C als allgemein behandeln (mit der erwähnten Ausnahme des Status von Arrays zweiter Klasse ), warum wollen wir keine Strukturen übergeben oder zurückgeben? (Übrigens, IIRC, K & R1 sagten, dass das Übergeben von Strukturen auf dem Weg war und es in V7 cc funktionierte, als das Buch herauskam.)
Steve Summit
38

Zunächst, um zu zitieren C11, Kapitel §6.8.6.4, returnAussage, ( Hervorhebung von mir )

Wenn eine returnAnweisung mit einem Ausdruck ausgeführt wird, wird der Wert des Ausdrucks als Wert des Funktionsaufrufausdrucks an den Aufrufer zurückgegeben.

Die Rückgabe einer Strukturvariablen ist möglich (und korrekt), da der Strukturwert zurückgegeben wird. Dies ähnelt der Rückgabe eines primitiven Datentyps ( intz. B. Rückgabe ).

Wenn Sie andererseits ein Array zurückgeben , indem Sie das verwenden return <array_name>, wird im Wesentlichen die Adresse des ersten Elements des Arrays zurückgegeben. HINWEIS , das im Aufrufer ungültig wird, wenn das Array für die aufgerufenen Funktionen lokal war. Eine Rückgabe des Arrays auf diese Weise ist daher nicht möglich.

Also, TL; DR , es gibt nichts Besonderes mit structs, die Spezialität liegt in Arrays .


HINWEIS:

Nochmals zitieren C11, Kapitel §6.3.2.1, ( meine Betonung )

Außer wenn es der Operanden des IS - sizeofOperators, die _AlignofBedienungsperson oder den unären &Operators oder ein Stringliteral verwendet , um einen Array zu initialisieren, ein Ausdruck, den Typen hat ‚‘ Array vom Typ ‚‘ umgewandelt wird , in einen Ausdruck mit Typ ‚‘ Zeiger auf Typ '' , der auf das Anfangselement des Array-Objekts zeigt und kein l-Wert ist. [...]

Sourav Ghosh
quelle
Was genau ist OTOH ?!
1
@ Sukl Es ist die Abkürzung für "auf der anderen Seite" :)
Sourav Ghosh
1
@Sukl Ich denke, diese Abkürzungen sind ungefähr so ​​alt wie das Internet selbst. Sie wurden sicherlich während der Usenet-Ruhmestage viel benutzt und überleben immer noch in den meisten Foren. Zum Glück kann Google sie auch für Unbewusste entschlüsseln ;-) Und es gibt nur eine Handvoll, die heute häufig verwendet werden (die häufigsten)
Chi
@chi yes.Google ist ziemlich brillant und in der Lage, sie zu dekodieren.
1
@Sukl: Möglicherweise ist AcronymFinder nützlich, um Akronyme aufzuspüren.
Jonathan Leffler
11

structTypen haben nichts Besonderes ; Array- Typen haben etwas Besonderes , das verhindert, dass sie direkt von einer Funktion zurückgegeben werden.

Ein structAusdruck wird wie ein Ausdruck eines anderen Nicht-Array-Typs behandelt. es ergibt den Wert des struct. So können Sie Dinge wie tun

struct foo { ... };

struct foo func( void )
{
  struct foo someFoo;
  ...
  return someFoo;
}

Der Ausdruck ergibtsomeFoo den Wert des struct fooObjekts. Der Inhalt des Objekts wird von der Funktion zurückgegeben (auch wenn dieser Inhalt Arrays enthält).

Ein Array-Ausdruck wird anders behandelt. Wenn es sich nicht um den Operanden der sizeofoder unären &Operatoren handelt oder wenn es sich nicht um ein Zeichenfolgenliteral handelt, das zum Initialisieren eines anderen Arrays in einer Deklaration verwendet wird, wird der Ausdruck vom Typ "Array von T" in "Zeiger auf T" konvertiert ("decays"). und der Wert des Ausdrucks ist die Adresse des ersten Elements.

Sie können also kein Array nach Wert von einer Funktion zurückgeben, da jeder Verweis auf einen Array-Ausdruck automatisch in einen Zeigerwert konvertiert wird.

John Bode
quelle
-5

Strukturen haben standardmäßig öffentliche Datenelemente, so dass es bei Strukturen möglich ist, auf Daten in main zuzugreifen, nicht jedoch in Klassen. Der Strukturumbruch ist also gültig.

hoh
quelle
1
Haben Sie gesehen, dass die Frage über C ist? In C gibt es keine public/ privateUnterscheidung und es gibt keine classes. Die Frage ist, warum a structin C benötigt wird, um den Wert eines Arrays zurückzugeben.
PJTraill