typedef Array fester Länge

Lesezeit: 6 Minuten

Benutzeravatar von 341008
341008

Ich muss einen 24-Bit-Datentyp definieren. Ich verwende char[3] den Typ darzustellen. Kann ich Typdef char[3] zu type24? Ich habe es in einem Codebeispiel ausprobiert. ich lege typedef char[3] type24; in meiner Header-Datei. Der Compiler hat sich darüber nicht beschwert. Aber wenn ich eine Funktion definiert habe void foo(type24 val) {} in meiner C-Datei hat es sich beschwert. Ich möchte in der Lage sein, Funktionen wie zu definieren type24_to_int32(type24 val) Anstatt von type24_to_int32(char value[3]).

Die Typedef wäre

typedef char type24[3];

Dies ist jedoch wahrscheinlich eine sehr schlechte Idee, da der resultierende Typ ein Array-Typ ist, Benutzer davon jedoch nicht sehen, dass es sich um einen Array-Typ handelt. Wenn es als Funktionsargument verwendet wird, wird es als Referenz übergeben, nicht als Wert, und die sizeof denn es wird dann falsch sein.

Eine bessere Lösung wäre

typedef struct type24 { char x[3]; } type24;

Sie möchten wahrscheinlich auch verwenden unsigned char Anstatt von charda letzteres eine implementierungsdefinierte Signiertheit hat.

  • Gibt es ein nettes Dokument, das die Eckfälle beschreibt, die mit der Übergabe von typdefinierten Arrays als Parameter verbunden sind? Zum Beispiel, wenn eine Funktion einen Parameter übernimmt type24 foowas wären die Größen, Arten und Bedeutungen von foo, *foo, **foo, &foound &&foo? Haben sich Bedeutung und Rechtmäßigkeit solcher Ausdrücke im Laufe der Jahre geändert?

    – Superkatze

    14. September 2012 um 15:51 Uhr

  • Erwähnenswert ist wahrscheinlich der Vorbehalt beim Strukturpacken, da ein 24-Bit-Datentyp möglicherweise auf etwas mit anders definierter Packsemantik wie RGB-Bilddaten abgebildet werden soll.

    – sch1

    27. Juni 2013 um 16:17 Uhr

  • @sh1: Bei allen modernen realen ABIs, die mir bekannt sind – selbst bei denen, bei denen ein falsch ausgerichteter Zugriff sehr teuer ist – erhalten Strukturen keine stärkeren Ausrichtungsanforderungen als ihre Mitglieder ohne die Struktur. Natürlich sollte OP oder jeder andere, der diesen Ansatz verwendet, meine Behauptung überprüfen, wenn es um das Verhalten und die Portabilität ihres Programms geht.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    2. August 2013 um 14:08 Uhr

  • @R .. Ein Teil davon ist irreführend – in C sind Arrays stets per Referenz übergeben, dh wenn Sie das als Argument an eine Funktion übergebene Array ändern, tun Sie dies global, nicht nur im Kontext der Funktion. Davon abgesehen könnte man auch argumentieren, dass es in C Arrays gibt stets als Wert übergeben, da wir einfach die Adresse des ersten Elements übergeben, das auf den Stack des aufgerufenen Stacks kopiert wird. In beiden Fällen ist die Antwort jedoch irreführend.

    – baibo

    4. August 2014 um 16:44 Uhr

  • @bobbogo: Dein Test ist fehlerhaft. 3 ist ein intund sizeof(int)!=3.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    18. Februar 2016 um 18:22 Uhr

Benutzeravatar von ysth
ysth

Sie wollen

typedef char type24[3];

C-Typ-Deklarationen sind auf diese Weise seltsam. Sie platzieren den Typ genau dort, wo der Variablenname stehen würde, wenn Sie eine Variable dieses Typs deklarieren würden.

  • ich habe erwartet typedef char[3] type24 aber es sieht so aus, als hätte ich mich geirrt :)). Gibt es eine Erklärung, warum das so ist?

    – Cătălina Sirbu

    23. August 2020 um 5:57 Uhr

  • @CătălinaSîrbu siehe die Rechts-Links-Regel zum Entschlüsseln von Deklarationen: cseweb.ucsd.edu/~ricko/rt_lt.rule.html

    – Gerhard Burger

    5. März 2021 um 10:45 Uhr

Benutzeravatar von Gerhard Burger
Gerhard Burger

Aus der Antwort von R..:

Dies ist jedoch wahrscheinlich eine sehr schlechte Idee, da der resultierende Typ ein Array-Typ ist, Benutzer davon jedoch nicht sehen, dass es sich um einen Array-Typ handelt. Wenn es als Funktionsargument verwendet wird, wird es als Referenz übergeben, nicht als Wert, und die sizeof dafür ist dann falsch.

Benutzer, die nicht sehen, dass es sich um ein Array handelt, werden höchstwahrscheinlich so etwas schreiben (was fehlschlägt):

#include <stdio.h>

typedef int twoInts[2];

void print(twoInts *twoIntsPtr);
void intermediate (twoInts twoIntsAppearsByValue);

int main () {
    twoInts a;
    a[0] = 0;
    a[1] = 1;
    print(&a);
    intermediate(a);
    return 0;
}
void intermediate(twoInts b) {
    print(&b);
}

void print(twoInts *c){
    printf("%d\n%d\n", (*c)[0], (*c)[1]);
}

Es wird mit den folgenden Warnungen kompiliert:

In function ‘intermediate’:
warning: passing argument 1 of ‘print’ from incompatible pointer type [enabled by default]
    print(&b);
     ^
note: expected ‘int (*)[2]’ but argument is of type ‘int **’
    void print(twoInts *twoIntsPtr);
         ^

Und erzeugt die folgende Ausgabe:

0
1
-453308976
32767

Benutzeravatar von Steve Jessop
Steve Jessop

Arrays können in C nicht als Funktionsparameter per Wert übergeben werden.

Sie können das Array in eine Struktur einfügen:

typedef struct type24 {
    char byte[3];
} type24;

und übergeben Sie das dann als Wert, aber dann ist es natürlich weniger bequem zu verwenden: x.byte[0] Anstatt von x[0].

Ihre Funktion type24_to_int32(char value[3]) übergibt tatsächlich den Zeiger, nicht den Wert. Es ist genau gleichbedeutend mit type24_to_int32(char *value)und die 3 wird ignoriert.

Wenn Sie glücklich sind, vorbei an Zeiger zu gehen, Sie könnte Bleiben Sie beim Array und tun Sie Folgendes:

type24_to_int32(const type24 *value);

Dadurch wird ein Zeiger auf ein Array übergeben, nicht ein Zeiger auf das erste Element, also verwenden Sie es wie folgt:

(*value)[0]

Ich bin mir nicht sicher, ob das wirklich ein Gewinn ist, denn wenn Sie versehentlich schreiben value[1] dann passiert etwas blödes.

Um den Array-Typ richtig als Funktionsargument oder Vorlagenparameter zu verwenden, erstellen Sie eine Struktur anstelle einer Typedef und fügen Sie dann eine hinzu operator[] an die Struktur, damit Sie die Array-ähnliche Funktionalität wie folgt beibehalten können:

typedef struct type24 {
  char& operator[](int i) { return byte[i]; }
  char byte[3];
} type24;

type24 x;
x[2] = 'r';
char c = x[2];

  • Dies ist eine C-Frage, nicht C++. Weder char& Noch operator[] sind Dinge, die in C existieren.

    – Michael Morris

    5. Dezember 2018 um 1:04 Uhr

Daniels Benutzeravatar
Daniel

Hier ist ein kurzes Beispiel dafür, warum das Typedef-Array verwirrend inkonsistent sein kann. Die anderen Antworten bieten eine Problemumgehung.

#include <stdio.h>
typedef char type24[3];

int func(type24 a) {
        type24 b;
        printf("sizeof(a) is %zu\n",sizeof(a));
        printf("sizeof(b) is %zu\n",sizeof(b));
        return 0;
}

int main(void) {
        type24 a;
        return func(a);
}

Dies erzeugt die Ausgabe

sizeof(a) is 8
sizeof(b) is 3

weil type24 als Parameter ein Zeiger ist. (In C werden Arrays immer als Zeiger übergeben.) Der gcc8-Compiler gibt glücklicherweise standardmäßig eine Warnung aus.

  • Dies ist eine C-Frage, nicht C++. Weder char& Noch operator[] sind Dinge, die in C existieren.

    – Michael Morris

    5. Dezember 2018 um 1:04 Uhr

Benutzeravatar von PiCTo
PiCTo

Aufbauend auf der akzeptierten Antwort kann ein mehrdimensionaler Arraytyp, dh ein Array fester Länge von Arrays fester Länge, nicht mit deklariert werden

typedef char[M] T[N];  // wrong!

Stattdessen kann der 1D-Array-Zwischentyp wie in der akzeptierten Antwort deklariert und verwendet werden:

typedef char T_t[M];
typedef T_t T[N];

oder, T kann in einer einzigen (wohl verwirrenden) Anweisung deklariert werden:

typedef char T[N][M];

was eine Art von definiert N Arrays von M chars (Achten Sie hier auf die Reihenfolge).

1426210cookie-checktypedef Array fester Länge

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

Privacy policy