Guten Morgen zusammen!
In C haben die angelegten Variablen ja bekanntlich einen zufälligen
Inhalt wenn Sie nicht initialisiert werden. Für Arrays gilt das gleiche.
Wie sieht es mit Strukturen aus?
Ich habe ein paar Versuche nach folgendem Prinzip gemacht
1
typedefstruct{
2
int16_tskalar;
3
int16_tvektor[15];
4
}struktur_t;
5
struktur_tmein_array;
Anscheinend haben alle Elemente auf die ich zugreifen kann den Wert 0.
Kann das jemand bestätigen oder ist das "Zufall"?
Eine weitere Frage: wie kann ich möglichst einfach ein zweidimensionales
Array mit Null füllen? Spricht etwas dagegen:
1
intarray[n][m];
2
memset(array,0,sizeof(int)*n*m);
Letzte Frage: Ist es richtig, dass ich mich nicht darauf verlassen kann,
dass oben genannte Struktur fein säuberlich hintereinander im Speicher
liegt? Eine Null-Initialisierung nach obigem Beispiel würde also
rausfallen. Gibt es da eine einfache Alternative?
Gruß Dennis
Dennis S. schrieb:> In C haben die angelegten Variablen ja bekanntlich einen zufälligen> Inhalt wenn Sie nicht initialisiert werden.
nein, alle globalen und static Variablen werden mit initialisiert.
> Letzte Frage: Ist es richtig, dass ich mich nicht darauf verlassen kann,> dass oben genannte Struktur fein säuberlich hintereinander im Speicher> liegt?
wie soll das gehen, wie sie nicht hintereinander im Speicher liegt, dann
könnte man ja auch nicht darauf zugreifen?
> Eine Null-Initialisierung nach obigem Beispiel würde also> rausfallen.
nein, genauso kann man es machen.
> Gibt es da eine einfache Alternative?
braucht man ja nicht.
Peter II schrieb:>> Letzte Frage: Ist es richtig, dass ich mich nicht darauf verlassen kann,>> dass oben genannte Struktur fein säuberlich hintereinander im Speicher>> liegt?> wie soll das gehen, wie sie nicht hintereinander im Speicher liegt, dann> könnte man ja auch nicht darauf zugreifen?
Das Stichwort lautet hier Alignment. Aus Optimierungs- und
Architekturgründen kann sehr wohl zwischen den einzelnen
Strukturelementen etwas Platz gelassen werden, damit mit an von der
Prozessorarchitektur bevorzugten Adressgrenzen ausgerichteten Zugriffen
gearbeitet werden kann.
Nehmen wir mal ein 32-Bit-System und folgende Struktur an:
1
structbla
2
{
3
uint8_twert1;
4
uint32_twert2;
5
}
Wird die Struktur selbst an einer für 32-Bit-Zugriffen geeigneten
Adresse (also einer restlos durch 4 teilbaren) ausgerichtet, läge das
Strukturelement wert2 um eins "daneben".
Etliche 32-Bit-Systeme können hier keinen 32-Bit-Zugriff ausführen,
sondern müssen aufwendig mit Einzelbyte-Zugriffen arbeiten, so daß die
Performance hier massiv leidet.
Deswegen werden hier drei Füllbytes eingeschoben, so daß ein sizeof
der Struktur den Wert 8 und nicht, wie erwartet, 5 zurückgibt.
Mit compilerspezifischen Anweisungen à la #pragma pack oder _packed_
(näheres siehe des Compilers Dokumentation) lässt sich die "langsame"
Variante erzwingen.
Peter II schrieb:> Dennis S. schrieb:>> In C haben die angelegten Variablen ja bekanntlich einen zufälligen>> Inhalt wenn Sie nicht initialisiert werden.>> nein, alle globalen und static Variablen werden mit initialisiert.
Ach, daran habe ich nicht gedacht! Es handelt sich bei meiner Struktur
tatsächlich um eine Globale.
>> Letzte Frage: Ist es richtig, dass ich mich nicht darauf verlassen kann,>> dass oben genannte Struktur fein säuberlich hintereinander im Speicher>> liegt?> wie soll das gehen, wie sie nicht hintereinander im Speicher liegt, dann> könnte man ja auch nicht darauf zugreifen
Aus diesem Thread lese ich das irgendwie anders:
Beitrag "Aufbau von Structs im Speicher">> Gibt es da eine einfache Alternative?> braucht man ja nicht.
Doch, FALLS einzelnen Elemente der Struktur nicht hintereinander im
Speicher liegen. Ansonsten:
1
struktur_tmein_array;
2
memset(&mein_array,0,sizeof(struktur_t));
Vielleicht kann jemand noch mal erläutern wo der Unterschied zwischen
meiner Struktur (die kann auch anders aussehen!) und dem verlinkten
Thread ist?
Gruß Dennis
Rufus Τ. Firefly schrieb:> Das Stichwort lautet hier Alignment.
das spielt über für das nullen keine Rolle. Wenn die füllbytes da sind
werden sie auch mit 0 gefüllt.
Danke Rufus, das habe ich vorhin auch gefunden! Und bestätigt mich ja
auch ein wenig in meinen "Befürchtungen".. Also was bleibt mir? Alle
Elemente einzeln "Nullen"?
Gruß Dennis
Peter II schrieb:> Rufus Τ. Firefly schrieb:>> Das Stichwort lautet hier Alignment.>> das spielt über für das nullen keine Rolle. Wenn die füllbytes da sind> werden sie auch mit 0 gefüllt.
Kann es nicht sein, dass in den Füllbytes "fremde" Daten liegen?
Dennis S. schrieb:> Danke Rufus, das habe ich vorhin auch gefunden! Und bestätigt mich ja> auch ein wenig in meinen "Befürchtungen".. Also was bleibt mir? Alle> Elemente einzeln "Nullen"?
nein, brauchst du nicht. Selbst wenn Lücken vorhanden sind, werden sie
ja bei sizeof mit berücksichtig.
Alligment Lücken sind verschwendeter Platz
zur Reduzierung Variablen, auch in Strukturen, möglichst von Großen Typ
zum kleinen Typ sortieren.
Laut Standard werden übrigens nicht initialisierte Variablen beim Start
vom System auf 0 gesetzt.
Wer selbst ein Standard konformes System bauen will, muss das bei einem
Reset auch selbst so implementieren.
Volle schrieb:> zur Reduzierung Variablen, auch in Strukturen, möglichst von Großen Typ> zum kleinen Typ sortieren.
Kannst du dafür ein Beispiel geben?
Volle schrieb:> Laut Standard werden übrigens nicht initialisierte Variablen beim Start> vom System auf 0 gesetzt.
... sofern es Variablen sind, die der Initialisierung unterliegen, also
globale und statische.
ganz einfach rechne mal für beide Beispiele die Lücken aus wenn der
Prozessor ( wie viele) bei 32Bit Variable nur auf durch 4 teilbare
Adressen
und bei 16 Bit Variablen auf gerade Adresse zugreifen kann
gutes Beispiel:
uint32_t a;
uint32_t b;
uint16_t c;
uint16_t d;
uint8_t e;
uint8_t f;
uint8_t g;
uint8_t h;
schlechtes Beispiel
uint8_t f;
uint32_t a;
uint8_t e;
uint16_t c;
uint8_t h;
uint32_t b;
uint8_t g;
uint16_t d;
Strukturen haben bei 32Bit Prozessoren meist auch eine durch 4 teilbare
Startadresse.
Das legt die EABI in der Regel so fest und die Compiler sollten sich
dran halten.
Dennis S. schrieb:> Eine weitere Frage: wie kann ich möglichst einfach ein zweidimensionales> Array mit Null füllen? Spricht etwas dagegen:> int array[n][m];> memset(array, 0, sizeof(int) n m);
1
intarray[n][m]={0};
Das gilt auch für Strukturen. Sobald Du in der Initialisierungsliste
mindestens einem Element einen Wert gibst, werden alle anderen "nicht
genannten" Elemente mit 0 initialisiert.
Konrad S. schrieb:> Volle schrieb:>> Laut Standard werden übrigens nicht initialisierte Variablen beim Start>> vom System auf 0 gesetzt.>> ... sofern es Variablen sind, die der Initialisierung unterliegen, also> globale und statische.
ja,
aber bei lokalen nicht static prüft der Compiler ob zuerst gelesen oder
geschrieben wird und schimpft falls es falsch ist.
Bei globalen kann es das nicht.
Volle schrieb:> aber bei lokalen nicht static prüft der Compiler ob zuerst gelesen oder> geschrieben wird und schimpft falls es falsch ist.
daruf kann man sich aber nicht verlassen!
1
voidfoo(){
2
inti;
3
bar(&i);
4
printf("%d",i);
5
}
hier wird kein Compiler schimpfen, weil er nicht weiss ob i in bar
geschrieben wird oder nicht.
Bei Funktionsaufrufen enden die Überprüfungen (und auch die
Optimierungen)
Ich habe mal ein Tool geschrieben das die Zugriffe auf Variablen und
Konstanten auf Obj-Code Ebene für eine Gesamtsoftware analysiert.
bei ca 95% Vollständigkeit hab ich aufgehört.
Da ging es aber darum Elemente zu finden die nicht gelesen werde
und überflüssig sind.