Salu zusammen
Ich habe hier wieder mal ein Problem und blick echt nicht mehr durch.
Scheint als ob meine C Zeiten auch nicht mehr so aktuell sind. Komm
einfach nicht drauf. Wäre toll wenn mir jemand eine Lösung hätte.
Zum Problem:
Ich habe einen Stuct deklariert in a.h
typedef struct
{
char a;
char b;
char c[];
} s_x;
extern volatile s_x g_test_array;
Im File a.c möchte ich nun diesen Struct gerne initialisieren (a.h ist
in a.c includiert):
g_test_array.a = 1;
g_test_array.b = 2;
g_test_array.c[3] = {0x00,0xD4,0x34};
Mööööööp und da will er nicht mehr ;o) Wie initialisiere ich ein Array
welches sich innerhalb eines Structs befindet wenn ich vorgegebene Werte
habe? Dass ich es mit einer Schleife initialisieren kann ist mir klar,
dass habe ich an anderer Stelle auch gemacht und das funktioniert. Also
ala
for(i=0;i<3;i++)
g_test_array[i] = 0x00;
So kann ich ja aber kein Array initialisieren. Hoffe ich konnte
verständlich machen was ich möchte... Wäre toll wenn jemand eine Lösung
hätte. Bin gerade mit Fonts am basteln und da will ich das irgendwie
flexiebel gestalten. Ich kann bei der Deklaration des Structs auch nicht
sagen wie gross das Array "c" werden wird...
Es Grüessli aus der verschneiten Schweiz
RS4B5
RS4B5 schrieb:> Salu zusammen>> Ich habe hier wieder mal ein Problem und blick echt nicht mehr durch.> Scheint als ob meine C Zeiten auch nicht mehr so aktuell sind. Komm> einfach nicht drauf. Wäre toll wenn mir jemand eine Lösung hätte.>> Zum Problem:>> Ich habe einen Stuct deklariert in a.h>> typedef struct> {> char a;> char b;> char c[];> } s_x;
das geht so nicht.
Wie groß ist denn das Array? Da die Größe hier nicht bekannt ist, ist
damit auch die Strukturgröße nicht bekannt. Ergo weiß der Compiler auch
nicht, wieviel Platz für eine derartige Variable im Speicher zu
reservieren ist.
> Ich kann bei der Deklaration des Structs auch nicht> sagen wie gross das Array "c" werden wird...
Das musst du aber. Denn der Compiler bzw. Linker müssen ja wissen,
wieviel Speicher sie reservieren müssen.
> Im File a.c möchte ich nun diesen Struct gerne initialisieren (a.h ist> in a.c includiert):>> g_test_array.a = 1;> g_test_array.b = 2;> g_test_array.c[3] = {0x00,0xD4,0x34};
Das sind aber keine Initialisierungen. Das sind Zuweisungen.
Du musst Zuweisungen und Initialisierungen streng auseinander halten,
der Compiler tut das nämlich auch.
volatile s_x g_test_array =
{ 1, 2, { 0x00, 0xD4, 0x34 } };
Initialisierungen stehen IMMER bei der Vereinbarung (der Definition)
einer Variablen. Dies deshalb, weil Initialisierungen IMMER gemacht
werden, wenn eine Variable 'zur Welt' kommt.
Alles andere dahinter kann keine Initialisierung mehr sein, sondern ist
eine Zuweisung. Und Arrays kann man nicht als ganzes zuweisen, sondern
nur auf Elementebene.
Deine Deklaration
> extern volatile s_x g_test_array;
könnte bei der Definition so aussehen:
volatile s_x g_test_array = {1, 2, {0x00,0xD4,0x34}};
um die (beim Element c falsche) Laufzeitinitialisierung
> g_test_array.a = 1;> g_test_array.b = 2;> g_test_array.c[3] = {0x00,0xD4,0x34};
durch eine Kompilezeitinitialisierung zu ersetzen.
> for(i=0;i<3;i++)> g_test_array[i] = 0x00;
Das klappt mit deiner g_test_array Deklaration oben nicht, weil du kein
Array definiert hast. Eine Arraydeklaration müsste dafür so aussehen:
extern volatile s_x g_test_array[3];
Und bei der entsprechenden Definition wird das Array auch, wenn global,
vom Startupcode mit 0 initialisiert, so dass du die for-Schleife sparen
kannst.
Ok, vielen Dank! Jetzt ist es schon klarer... aber ;o)
Nun habe ich in ein anderes Problem
Wie bekomme ich nun diesen Struct Global?
Wenn ich in a.h deklariere
typedef struct
{
char a;
char b;
char c[];
} s_x;
extern volatile s_x g_test_array;
und in a.c über eine Funktion, welche ich aus Main aufrufe
initialisieren
void Init_struct(void)
{
volatile s_x g_test_array = { 1, 2, { 0x00, 0xD4, 0x34 } };
}
und dann in main auf c zugreifen möchte, geht das nicht? Was hab ich
denn nun noch nicht verstanden? Entschuldigung, denke ich muss wieder
mal ein C Buch anschauen
Grüessli
wird das Element "c" nur als Pointer definiert und nicht als Array!
Und dieser Pointer enthält noch nicht die Adresse eines geeigneten
Arrays (denn es gibt ja gar kein Array, weil Du dachtest, Du würdest
eines anlegen, obwohl Du nur einen Pointer angelegt hast).
Wenn Du nun
1
for(i=0;i<3;i++)
2
g_test_array.c[i]=0x00;
ausführst, schreibst Du mit einem uninitialisieren Pointer in Deinem
Speicher herum (wahrscheinlich die Adresse 0x0000, 0x0001 und 0x0002,
was immer dort auch liegt, vielleicht SFR?).
RS4B5 schrieb:> void Init_struct(void)> {> volatile s_x g_test_array = { 1, 2, { 0x00, 0xD4, 0x34 } };> }
weil es hier bei beenden der funktion gekillt wird
danach ist es nicht mehr existent ..
bzw wurde der speicher wieder freigegeben
wenn du es global machen willst .. tu es doch
Dosmo schrieb:> Bitte Vorsicht!> Mit Deiner Deklaration>>
1
>typedefstruct
2
>{
3
>chara;
4
>charb;
5
>charc[];
6
>}s_x;
7
>
>> wird das Element "c" nur als Pointer definiert und nicht als Array!
Ich kann das nur noch einmal unterstreichen. Es sieht nämlich so aus,
als ob RS4B5 diesen Problemkreis inständig ignoriert.
In C (ausser den neuen dynamischen Arrays) gibt es keine
Datenstrukturen, die sich irgendwie selbstständig an äussere
Gegebenheiten anpassen. Wenn du so etwas brauchst, dann musst du das
selbst machen. Jeder Datentyp (auch eine Struktur ist ein Datentyp) hat
eine genau definierte Länge und muss die auch haben. Das ist wichtig,
weil man aus jedem Datentyp wiederrum ein Array machen können muss und
spätestens dann muss die Größe eines Elements bekannt und auch immer
gleich sein, sonst funktioniert der ganze Arraymechanismus nicht.
Karl Heinz Buchegger schrieb:>> wird das Element "c" nur als Pointer definiert und nicht als Array!>> Ich kann das nur noch einmal unterstreichen.
Ich nicht, denn es ist falsch.
c ist in dem Beispiel kein Pointer. Es ist ein echtes Array innerhalb
der Struktur.
Karl Heinz Buchegger schrieb:> Jeder Datentyp (auch eine Struktur ist ein Datentyp) hat> eine genau definierte Länge und muss die auch haben.
Und in dem Beispiel ist diese Größe 2 (nur a und b), nicht etwa 4.
Karl Heinz Buchegger schrieb:> Das ist wichtig,> weil man aus jedem Datentyp wiederrum ein Array machen können muss und> spätestens dann muss die Größe eines Elements bekannt und auch immer> gleich sein, sonst funktioniert der ganze Arraymechanismus nicht.
Richtig, weshalb man auch nicht sinnvoll ein Array aus s_x bilden kann,
und sofort eine fette Warnung kassiert, wenn man es doch probiert.
Stefan Ernst schrieb:> Karl Heinz Buchegger schrieb:>>> wird das Element "c" nur als Pointer definiert und nicht als Array!>>>> Ich kann das nur noch einmal unterstreichen.>> Ich nicht, denn es ist falsch.> c ist in dem Beispiel kein Pointer.
Ich war mir nicht mehr sicher, was in diesem Fall tatsächlich allokiert
wird, daher gab ich Dosmo das in dubio.
> Es ist ein echtes Array innerhalb> der Struktur.
... welches allerdings nicht allokiert wird.
RS4B5 schien der Ansicht zu sein, das er mittels
g_test_array.c[3] = {0x00,0xD4,0x34};
dieses Array nachträglich auf eine Länge von 3 Elementen bringen kann,
was so natürlich nicht geht. Man kann das machen, wenn man mittels
malloc sich selbst um den Speicher kümmert. Aber ob der TO diesen Weg
gehen möchte, wage ich zu bezweifeln.
Auf jeden Fall: Danke für die Korrektur.
Stefan Ernst schrieb:> Ich nicht, denn es ist falsch.> c ist in dem Beispiel kein Pointer. Es ist ein echtes Array innerhalb> der Struktur.
Und was genau ist ein Array mit einer nicht definierten Zahl von
Einträgen? Wie viele Einträge gibt es dann?
Karl Heinz Buchegger schrieb:> Man kann das machen, wenn man mittels> malloc sich selbst um den Speicher kümmert.
Ich hätte erwartet, dass man die entsprechende Allokierung auch über die
explizite Initialisierung erreichen kann:
1
volatiles_xg_test_array={1,2,{0x00,0xD4,0x34}};
Beim GCC funktioniert das auch. Es produziert allerdings auch eine
Warnung, so dass das vielleicht auch nur eine GCC-Eigenart ist, die
nicht von Standard abgedeckt ist.
Mark Brandis schrieb:> Stefan Ernst schrieb:>> Ich nicht, denn es ist falsch.>> c ist in dem Beispiel kein Pointer. Es ist ein echtes Array innerhalb>> der Struktur.>> Und was genau ist ein Array mit einer nicht definierten Zahl von> Einträgen? Wie viele Einträge gibt es dann?
Keine. Das Array existiert nur logisch für den Compiler. Aber in der
Struktur wird kein Speicher dafür reserviert.
Solche Variablen kann man nur verwenden, indem man sich selbst mittels
malloc entsprechend großen Speicher anlegt.
zb
1
typedefstruct
2
{
3
chara;
4
charb;
5
charc[];
6
}s_x;
7
8
9
intmain()
10
{
11
// allokieren und für das Array 3 Elemente anlegen.
Mark Brandis schrieb:> Stefan Ernst schrieb:>> Ich nicht, denn es ist falsch.>> c ist in dem Beispiel kein Pointer. Es ist ein echtes Array innerhalb>> der Struktur.> Und was genau ist ein Array mit einer nicht definierten Zahl von> Einträgen? Wie viele Einträge gibt es dann?
Ich vermute es geht um diese Punkte:
http://www.dclc-faq.de/kap2.htmStefan Ernst schrieb:> Karl Heinz Buchegger schrieb:>> Man kann das machen, wenn man mittels>> malloc sich selbst um den Speicher kümmert.>> Ich hätte erwartet, dass man die entsprechende Allokierung auch über die> explizite Initialisierung erreichen kann:volatile s_x g_test_array = { 1, 2, {
0x00, 0xD4, 0x34 } };
Lies Karl-Heinz' ersten Beitrag. ;-)
Mark Brandis schrieb:> Und was genau ist ein Array mit einer nicht definierten Zahl von> Einträgen? Wie viele Einträge gibt es dann?
Es gibt dann eine zum Zeitpunkt der Definition der Struktur unbestimmte
Anzahl von Einträgen. Nichtsdestotrotz ist dieses Array aber trotzdem
innerhalb der Struktur. Wenn du also auf c[42] zugreifst, dann wird
von der Adresse (Adresse_der_Struktur + 44) gelesen.
Karl Heinz Buchegger schrieb:> Allokierung. Anders kann man solche Konstrukte nicht sinnvoll verwenden.
Wobei ich einschränken muss.
Möglich, dass C99 da etwas definiert hat. Die Entwicklung zu C99 hab ich
etwas verschlafen, weil ich mich da schon lange auf C++ gestürzt hatte.
> Beim GCC funktioniert das auch. Es produziert allerdings auch eine> Warnung, so dass das vielleicht auch nur eine GCC-Eigenart ist, die> nicht von Standard abgedeckt ist.
Die statische Initialisierung ist eine Erweiterung. GCC hatte zuvor
schon zero-length arrays als Erweiterung, die als name[0] (statt name[]
aus C99) deklariert wurden und ähnlich funktionierten, aber nicht
statisch initialisiert werden können.
>> Stefan Ernst schrieb:>>> Ich nicht, denn es ist falsch.>>> c ist in dem Beispiel kein Pointer. Es ist ein echtes Array innerhalb>>> der Struktur.>>>> Und was genau ist ein Array mit einer nicht definierten Zahl von>> Einträgen? Wie viele Einträge gibt es dann?>>Keine. Das Array existiert nur logisch für den Compiler. Aber in der>Struktur wird kein Speicher dafür reserviert.
Verdammt, hier kann man echt noch was lernen. Ich hätte Stein und Bein
geschworen, daß "char* a" und "char a[]" das gleiche sind! Hut ab!
Dosmo schrieb:> Verdammt, hier kann man echt noch was lernen. Ich hätte Stein und Bein> geschworen, daß "char* a" und "char a[]" das gleiche sind! Hut ab!
Nicht an dieser Stelle.
In einer Argmuentliste einer Funktion hättest du recht gehabt.
Aber auch z.b. hier sind die beiden nicht identisch
a.h
1
intvalues[5];
b.h
1
externintvalues[];
c.h
1
externint*values;
b.h ist korrekt. c.h ist falsch.
Daher: Bei Aussagen, die in der Nähe sind von "Arrays und Pointer sind
eigentlich dasselbe", ist Vorsicht geboten! Denn ein Array ist kein
Pointer und ein Pointer ist kein Array.
Stefan Ernst schrieb:> Karl Heinz Buchegger schrieb:>>> wird das Element "c" nur als Pointer definiert und nicht als Array!>>>> Ich kann das nur noch einmal unterstreichen.>> Ich nicht, denn es ist falsch.> c ist in dem Beispiel kein Pointer. Es ist ein echtes Array innerhalb> der Struktur.
Nein. Es ist kein echtes Array, es hat "incomplete type". Man kann also
zB kein sizeof darauf verwenden.
C99 nennt sowas "flexible array member"; es ist als letzte Komponente
(und nur dort) von Strukturen erlaubt.
Syntaktisch sieht es auch wie ein char c[] in einer
Deklaration/Parameterliste, ist semantisch aber was anderes.
Johann L. schrieb:> C99 nennt sowas "flexible array member"
Das ist übrigens einer der wenigen Punkte, an denen die C-Compiler von
Microsoft zu C99 kompatibel sind, die unterstützen so etwas auch.
Karl Heinz Buchegger schrieb:>> Verdammt, hier kann man echt noch was lernen. Ich hätte Stein und Bein>> geschworen, daß "char* a" und "char a[]" das gleiche sind! Hut ab!>> Nicht an dieser Stelle.> In einer Argmuentliste einer Funktion hättest du recht gehabt.
Aber auch nur da, als Sonderfall. Überall sonst sind beide
unterschiedlich.