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])
.
typedef Array fester Länge
341008
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 char
da 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 foo
was wären die Größen, Arten und Bedeutungen vonfoo
,*foo
,**foo
,&foo
und&&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 einint
undsizeof(int)!=3
.– R.. GitHub HÖR AUF, EIS ZU HELFEN
18. Februar 2016 um 18:22 Uhr
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
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
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&
Nochoperator[]
sind Dinge, die in C existieren.– Michael Morris
5. Dezember 2018 um 1:04 Uhr
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&
Nochoperator[]
sind Dinge, die in C existieren.– Michael Morris
5. Dezember 2018 um 1:04 Uhr
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).