C leere Struktur – was bedeutet/macht das?

Lesezeit: 6 Minuten

Benutzeravatar von Billy Pilgrim
Billy Pilger

Ich habe diesen Code in einer Header-Datei für ein Gerät gefunden, das ich verwenden muss, und obwohl ich C seit Jahren mache, bin ich nie darauf gestoßen:

struct device {
};

struct spi_device {
    struct device dev;
};

und es verwendet wie in:

int spi_write_then_read(struct spi_device *spi, 
const unsigned char *txbuf, unsigned n_tx,
unsigned char *rxbuf, unsigned n_rx);

und auch hier:

struct spi_device *spi = phy->spi;

wo es gleich definiert ist.

Ich bin mir nicht sicher, was der Sinn dieser Definition ist. Es ist in einer Header-Datei für eine Linux-Anwendung des Boards, aber ich bin verblüfft über die Verwendung. Irgendwelche Erklärungen, Ideen? Jeder hat das schon einmal gesehen (ich bin sicher, einige von euch haben es :).

Vielen Dank! :bp:

  • Deklaration der Speicherzuordnung

    – Jebathon

    10. Juli 2014 um 20:13 Uhr

  • Ich bin mir nicht sicher, was es bedeuten soll, aber es ist kein Standard; Die Syntax für eine Struct-Deklaration erfordert mindestens einen Member. Vielleicht ist es ein Platzhalter für zukünftige Erweiterungen?

    – Keith Thompson

    10. Juli 2014 um 20:15 Uhr


  • Es scheint nichts zuzuordnen…

    – Billy Pilgrim

    10. Juli 2014 um 20:15 Uhr

  • Normalerweise ist es keine leere Struktur… Wie für warum Dies wurde in diesem Fall getan, es ist schwer zu sagen, ohne mehr Kontext.

    – Maisstängel

    10. Juli 2014 um 20:30 Uhr

  • Eine Möglichkeit besteht darin, dass es früher ein Mitglied in der Struktur “Gerät” gab, jemand dieses Mitglied gelöscht hat, weil es nicht mehr benötigt wurde, und vergessen hat, die Struktur zu löschen, oder es nicht gelöscht hat, weil es mehr Codeänderungen erforderte.

    – Etienne

    10. Juli 2014 um 21:15 Uhr

Benutzeravatar von ouah
ouah

Dies ist nicht C, da C-Strukturen mindestens ein benanntes Mitglied enthalten müssen:

(C11, 6.7.2.1 Struktur- und Vereinigungsspezifizierer p8) “Wenn die Strukturdeklarationsliste keine benannten Mitglieder enthält, weder direkt noch über eine anonyme Struktur oder eine anonyme Vereinigung, ist das Verhalten undefiniert.”

aber eine GNU C-Erweiterung:

GCC erlaubt einer C-Struktur, keine Member zu haben:

struct empty {
};

Die Struktur hat die Größe Null

https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html

Ich weiß nicht, was der Zweck dieses Konstrukts in Ihrem Beispiel ist, aber im Allgemeinen denke ich, dass es als Vorwärtsdeklaration des Strukturtyps verwendet werden kann. Beachten Sie, dass es in C++ erlaubt ist, eine Klasse ohne Member zu haben.

In Linux 2.4 gibt es ein Beispiel für einen leeren Strukturtyp mit bedingter Kompilierung in der Definition von spin_lock_t Geben Sie alias im Linux-Kernel 2.4 ein (in include/linux/spinlock.h):

#if (DEBUG_SPINLOCKS < 1)

/* ... */

typedef struct { } spinlock_t;

#elif (DEBUG_SPINLOCKS < 2)

/* ... */

typedef struct {
    volatile unsigned long lock;
} spinlock_t;

#else /* (DEBUG_SPINLOCKS >= 2) */

/* ... */

typedef struct {
    volatile unsigned long lock;
    volatile unsigned int babble;
    const char *module;
} spinlock_t;

#endif

Der Zweck besteht darin, Platz zu sparen, ohne die Funktions-API gegebenenfalls ändern zu müssen DEBUG_SPINLOCKS < 1. Es erlaubt auch, Dummy-Objekte (mit der Größe Null) zu definieren spinlock_t.

Ein weiteres Beispiel im (neueren) Linux-Kernel eines Hacks mit einer leeren Struktur, der mit bedingter Kompilierung in include/linux/device.h verwendet wird:

struct acpi_dev_node {
#ifdef CONFIG_ACPI
    void *handle;
#endif
};

Siehe die Diskussion mit Greg Kroah-Hartman für dieses letzte Beispiel hier:

https://lkml.org/lkml/2012/11/19/453

  • Es würde ein Problem beim Weiterleiten von Deklarationen im vom OP gesendeten Code geben: struct spi_device ist definiert (und nicht deklariert), daher muss der Compiler wissen, wie viel er dafür zuweisen muss.

    – rslemos

    10. Juli 2014 um 20:29 Uhr

  • @ouah Ich denke, wir kratzen uns alle am Kopf darüber, warum zum Teufel eine solche Definition jemals gemacht wird. Ich entschuldige mich für meinen Text; Wenn ich es jetzt noch einmal lese, fühlt es sich an, als würde ich Ihre Antwort kritisieren. Tut mir leid, das war ich nicht.

    – rslemos

    10. Juli 2014 um 20:34 Uhr

  • Ein Problem mit leeren Strukturen ist, wenn sie es auch haben sizeof Sein 0 dann verstößt ein Array davon gegen die Regel, dass unterschiedliche Objekte unterschiedliche Adressen haben müssen. Was passiert zum Beispiel mit struct device d[20], *ptr; for (ptr = d; ptr < d + 20; ++ptr) ?

    – MM

    10. Juli 2014 um 23:26 Uhr


  • @MattMcNabb – der Link zu gcc.gnu.org sagt “G++ behandelt leere Strukturen, als ob sie ein einzelnes Mitglied vom Typ char hätten”, also bezweifle ich sizeof jemals gleich wäre 0

    – cegfehler

    11. Juli 2014 um 6:22 Uhr


  • @cegfault: g++ kompiliert C++, und die Regeln dafür sind in C++ anders (ein weiteres Beispiel dafür, warum “C/C++”-Fragen vermieden werden sollten!)

    – Leichtigkeitsrennen im Orbit

    11. Juli 2014 um 9:19 Uhr

Benutzeravatar von hackks
hackt

Das ist kein Standard-C.
C11: 6.2.5-20:

— Ein Strukturtyp beschreibt eine sequentiell belegte nichtleere Menge von Mitgliedern Objekte (und unter bestimmten Umständen ein unvollständiges Array), von denen jedes einen optional angegebenen Namen und einen möglicherweise unterschiedlichen Typ hat.

J.2 Undefiniertes Verhalten:

Das Verhalten ist unter folgenden Umständen undefiniert:
….
Eine Struktur oder Vereinigung wird ohne benannte Mitglieder definiert (einschließlich der indirekt über anonyme Strukturen und Vereinigungen spezifizierten) (6.7.2.1).

GCC verwendet es als Verlängerung (dort wird nicht genauer angegeben, wann/wo es verwendet werden sollte). Wenn Sie dies in einem beliebigen Programm verwenden, wird es Compiler-spezifisch.

  • Für den Datensatz erlaubt C++ dies ausdrücklich ([C++11: 9/1]).

    – Leichtigkeitsrennen im Orbit

    11. Juli 2014 um 9:18 Uhr

  • @LightnessRacesinOrbit; Ja. Ich weiss. Ich habe es vermieden, dies hinzuzufügen, weil nur das C-Tag vorhanden ist.

    – Hacken

    11. Juli 2014 um 9:29 Uhr

  • Yep hätte ich genauso gemacht. Wollte es nur anmerken 🙂

    – Leichtigkeitsrennen im Orbit

    11. Juli 2014 um 10:01 Uhr

Ein Grund, dies für eine Bibliothek zu tun, könnte sein, dass die Bibliotheksentwickler nicht möchten, dass Sie die Interna dieser Strukturen kennen oder in sie eingreifen. In diesen Fällen können sie eine “Schnittstellen”-Version der Strukturen bereitstellen spi_device/device (was Sie sehen können) und eine zweite Typdefinition haben, die eine andere Version dieser Strukturen zur Verwendung innerhalb der Bibliothek mit den tatsächlichen Mitgliedern definiert.

Da Sie mit diesem Ansatz nicht auf Strukturmitglieder zugreifen oder selbst kompatible Strukturen dieses Typs erstellen können (da selbst Ihr Compiler die tatsächliche Größe dieser Struktur nicht kennen würde), funktioniert dies nur, wenn die Bibliothek selbst die Strukturen erstellt und Sie immer nur übergibt verweist darauf, und Sie müssen keine Mitglieder ändern.

  • Klingt so, als würden Sie über undurchsichtige Strukturen sprechen – das heißt, eine Struktur, die deklariert, aber nicht definiert wurde, wie in struct device;. Aber die Frage zeigt etwas anderes: Die Struktur wurde als leer definiert.

    – hmjail

    13. Dezember 2016 um 15:59 Uhr

Wenn Sie eine leere Struktur als erstes Element einer anderen Struktur hinzufügen, kann die leere Struktur als “Markierungsschnittstelle” dienen, dh wenn Sie einen Zeiger auf diese äußere Struktur auf einen Zeiger der inneren Struktur umwandeln und die Umwandlung erfolgreich ist, wissen Sie das die äußere Struktur ist als etwas “markiert”.

Es könnte auch nur ein Platzhalter für zukünftige Entwicklungen sein, nicht sicher. Hoffe das hilft

Das ist gültiges C

struct empty;
struct empty *empty;

und erleichtert die Verwendung von Adressen undurchsichtiger Speicherbereiche.

Solche Adressen werden normalerweise von Bibliothekssubroutinen erhalten und an diese weitergegeben.

So etwas wird zum Beispiel in stdio.h gemacht

1409400cookie-checkC leere Struktur – was bedeutet/macht das?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy