struct mit buffer und Länge
Verfasst: 21.09.2025, 12:49
Tach zusammen :-)
Ich hab mir einige Gedanken gemacht, welche Möglichkeiten es gibt, ein struct zu definieren, dass neben eines array buffers auch die Anzahl an Elementen dieses buffers speichert (statisch und unveränderlich).
(Es geht um plain C)
Auf dem Heap gibt es ja die Möglichkeit mittels "Flexible Array Member" (ab C99)
Oder zu ANSI C Zeiten: Da hatte man sich ja das ganze einfach mittels folgender Methode ermöglicht:
Beide Techniken setzten nun aber bekanntlich voraus, dass der Speicher zur Laufzeit alloziert wird.
Im Data-Segment oder auf dem Stack geht das nicht.
Da ich versuche, möglichst selten Speicher zur Laufzeit zu allozieren, platziere ich einige Elemente im Data-Segment (static oder falls möglich static const).
Ich hatte es jetzt in solchen Fällen mit einem Compound Literal gelöst:
Vorteil: Sehr einfach, sehr kompakt.
Nachteil: Es ist nicht garantiert, dass das Compount Literal (also der buffer) direkt an das eigentliche struct im Speicher anschliesst: Cache-Misses/TLB-Misses.
Alternativ dazu, habe ich mir jetzt folgendes überlegt:
Mit dieser Lösung ist der Anschluss im Speicher garantiert. So wie ich das sehe, könnte höchstens ein minimales padding durch das Alignment entstehen (je nach Typ des buffers).
Die Frage, die sich mir jetzt stellt: Lohnt sich das? Oder läuft es ohnehin fast immer darauf hinaus, dass der Compiler das Compound Literal gleich hinter dem struct platziert? Der buffer ist ja in meinem Beispiel 0 initialisiert und müsste daher im .bss Segment laden. Das struct hingegen enthält ja einen initialisierten pointer und ist daher folglich wohl im .data Segment.
Selbst wenn ich jetzt im Assemblercode nachschaue: Ohne das Verpacken in ein anonymes struct könnte sich das Speicherlayout wieder ändern (beim erneuten Compilieren).
Was denkt ihr dazu?
Edit1:
Kleiner Fehler im struct korrigiert.
Edit2:
Ich stelle erstaunt fest: mit buffer[0] = 0xCDU gibts im Terminal (cp 850, 437) tatsächlich die Deutschland-Flagge in schwarzweiss :-X
Ich hab mir einige Gedanken gemacht, welche Möglichkeiten es gibt, ein struct zu definieren, dass neben eines array buffers auch die Anzahl an Elementen dieses buffers speichert (statisch und unveränderlich).
(Es geht um plain C)
Auf dem Heap gibt es ja die Möglichkeit mittels "Flexible Array Member" (ab C99)
Code: Alles auswählen
struct s
{
int cap;
unsigned char buffer[];
};
Code: Alles auswählen
struct s
{
int cap;
unsigned char buffer[1];
};
Im Data-Segment oder auf dem Stack geht das nicht.
Code: Alles auswählen
struct s * foo = malloc(sizeof(*foo) + sizeof(foo->buf[0]) * SIZE);
Ich hatte es jetzt in solchen Fällen mit einem Compound Literal gelöst:
Code: Alles auswählen
struct s_strbuf strbuf = { .cap = SIZE, .Buf = (unsigned char[SIZE]){ 0 } };
Nachteil: Es ist nicht garantiert, dass das Compount Literal (also der buffer) direkt an das eigentliche struct im Speicher anschliesst: Cache-Misses/TLB-Misses.
Alternativ dazu, habe ich mir jetzt folgendes überlegt:
Code: Alles auswählen
static struct
{
struct s_strbuf strbuf; unsigned char buf[SIZE];
} block = { .strbuf.cap = SIZE, .strbuf.Buf = block.buf, .buf = { 0 } }; // Selbstreferenz nur bezüglich Adresse -> OK
Code: Alles auswählen
void func(struct s_strbuf * Strbuf)
{
for(int i = 0; i < Strbuf->cap; i += 1)
Strbuf->Buf[i] = 0xCDU;
return;
}
int main(void)
{
func(&block.strbuf);
return 0;
}
Die Frage, die sich mir jetzt stellt: Lohnt sich das? Oder läuft es ohnehin fast immer darauf hinaus, dass der Compiler das Compound Literal gleich hinter dem struct platziert? Der buffer ist ja in meinem Beispiel 0 initialisiert und müsste daher im .bss Segment laden. Das struct hingegen enthält ja einen initialisierten pointer und ist daher folglich wohl im .data Segment.
Selbst wenn ich jetzt im Assemblercode nachschaue: Ohne das Verpacken in ein anonymes struct könnte sich das Speicherlayout wieder ändern (beim erneuten Compilieren).
Was denkt ihr dazu?
Edit1:
Kleiner Fehler im struct korrigiert.
Edit2:
Ich stelle erstaunt fest: mit buffer[0] = 0xCDU gibts im Terminal (cp 850, 437) tatsächlich die Deutschland-Flagge in schwarzweiss :-X