Hallo,
ich habe ein paar Startschwierigkeiten mit "structs"
Folgendes habe ich in folgenden Dateien:
_________________________________________________
main.h:
struct T_Ringbuffer
{
char Soll;
char Ist;
char Buffer[RINGBUFFERGROSSE];
};
volatile extern struct T_Ringbuffer TX_Ringbuffer;
________________________________________________
uart.h:
volatile extern struct T_Ringbuffer TX_Ringbuffer;
________________________________________________
uart.c:
void shift_to_uart_tx_buffer(struct T_Ringbuffer *TX_Ringbuffer)
{
TX_Ringbuffer.Soll = 5; //(hierauf bezieht sich die Errormeldung)
}
________________________________________________
Fehlermeldung:
Error[Pe154]: expression must have struct or union type
Frage:
Was muss ich ändern, damit die Funktion in der uart.c das struct
verarbeiten kann...?
mfg und danke schonmal im voraus.
Du übergibst einen Pointer auf die Struktur.
Probier mal TX_Ringbuffer->Soll = 5 bzw. *TX_Ringbuffer->Soll = 5
Kann's leider grad nicht nachprüfen, aber ich meine, dass bei
struct-Zugriffen über Pointer das '->' anstelle des '.' zum Tragen
kommt.
Ralf
Danke für die Hilfe, funktioniert.
kann ich nun die Schlussfolgerung ziehen, dass es grundsätzlich zwei
Fälle gibt,
Fall 1 wäre die Übergabe eines Pointers in der Funktion, der auf das
struct zeigt.
In diesem Fall müsste ich
TX_Ringbuffer->Soll=5;
geschrieben werden
und Fall 2 wäre eine Funktion, die in etwa so aussehen würde:
void(struct structtyp meinstruct)
{
meinstruct.element = 10;
}
und ohne pointer arbeitet?
Ist das so korrekt?
struct.urschwach schrieb:> und Fall 2 wäre eine Funktion, die in etwa so aussehen würde:>> void(struct structtyp meinstruct)> {> meinstruct.element = 10;> }>> und ohne pointer arbeitet?>> Ist das so korrekt?
Nein. Dieser zweite Fall erzeugt beim Aufruf eine Kopie des Arguments,
verändert die Kopie und wirft sie beim Verlassen der Funktion wieder
weg.
Das nennt sich "call-by-value".
struct.urschwach schrieb:> Ist das so korrekt?
Im Prinzip ja - es gilt 2 Fälle zu unterscheiden.
Es ist völlig analog zum Fall
1
voidfoo1(inti)
2
{
3
i=5;
4
}
und
1
voidfoo2(int*i)
2
{
3
*i=5;
4
}
im ersten Fall bekommt die Funktion einen int als Kopie und kann diese
Kopie innerhalb der Funktion ändern wie sie lustig ist. Der Aufrufer
kriegt davon nichts mit, denn ... er hat ja nur eine Kopie seines
Wertes an die Funktion weitergegeben
1
intmain()
2
{
3
intk=8;
4
foo1(k);// k wird sich durch die Zuweisung in foo nicht ändern
5
}
Im zweiten Fall, gibt aber der Aufrufer die Adresse seiner eigenen
Variablen an die Funktion. Wenn daher die Funktion dort den Wert über
die Adresse ändert (genau das macht der * in *i = 5;), dann ändert sie
die Variable des Aufrufers
1
intmain()
2
{
3
intk=8;
4
foo2(&k);// hier greift die Funktion, mithilfe der Adresse auf
5
// das k des Aufrufers durch. foo2 verändert k!
6
}
Und mit structs ist das auch nicht anders. Vom Mechanismus her völlig
identisch. Ersetze "int" durch "struct T_Ringbuffer" und du hast wieder
die beiden Fälle.
Mit dem einen kleinen Problem, dass man
1
voidfoo3(structT_Ringbuffer*buf)
2
{
3
(*buf).Soll=5;
4
}
schreiben müsste (es geht um die Klammern)
Da das aber auf dauer mühsam ist, hat man für (*x).y eine andere
Schreibweise eingeführt, die x->y lautet. Also kann man anstelle des
Klammergewusels schreiben
1
voidfoo3(structT_Ringbuffer*buf)
2
{
3
buf->Soll=5;
4
}
und hat genau dasselbe.
Sagt denn da dein C-Buch nichts darüber? Eigentlich sollte das eine
nicht unbeträchtliche Anzahl von Seiten in deinem C-Buch einnehmen!
...also schonmal vielen Dank für die Antworten, aber irgendwo läuft es
immernoch nicht ganz so, wie gewünscht... ich denke ich bräuchte für den
Aufruf des structs in meiner Funktion nochmal einen Denkanstoss, bzw.
ich fürchte, dass ich das struct ev. falsch deklariert bzw. definiert
haben könnte...
Folgende Fehlermeldung gibt es beim Compilieren:
Na dann schau dir die Teile an. Der Compiler ist da eh schon sehr
spezifisch:
* Die Funktion will einen Pointer.
Einen struct T_Ringbuffer *
* Der Aufrufer veruscht aber ein Objekt reinzustopfen.
Es möchte einen struct T_Ringbuffer übergeben.
void foo( int * i )
{
...
}
int main()
{
int j;
foo( j );
}
wenn foo einen Pointer will, dann kann man nicht j reingeben ('das
Objekt reinstopfen') sondern man muss zb. die Adresse von j übergeben
int main()
{
int j;
foo( &j );
}
ACh Ronny. Halt doch einfach mal die Klappe. Kein Mensch kann was dafür,
dass du für C zu dämlich bist.
Das man eine Programmiersprache auch lernen muss, ist jetzt nicht
wirklich wahsinnig überraschend. Und auch nicht, das das nicht von heute
auf morgen geht.
hm also es ist ja nicht so, dass ich die Fehlermeldungen nicht
übersetzen kann, nur manchmal fixt man ein Problem und es entsteht
dadurch ein neues.
Also ich habe jetzt mal den Aufruf abgeändert zu:
...Eine Lösung für dieses Problem habe ich zur Abwechslung mal selber
finden können... wenn ich die "volatile" aus dem Code komplett entferne,
wird das Programm durchcompiliert...
Da ich aber in meinen (noch nicht implementierten)
Interrupt-Serviceroutinen ebenfalls auf die Werte aus dem struct
zugreifen möchte, hatte ich bisher versucht, diese Variablen volatile zu
halten...
Das folgende:
extern volatile struct T_Ringbuffer TX_Ringbuffer;
in uart.h und main.h so geht das nicht, zumal du beide Headerdateien in
main.c einbindest. Stichwort doppelte Deklaration. Nimm diese Zeile aus
den Headerdateien heraus. und schreibe folgfendes:
main.c:
volatile struct T_Ringbuffer TX_Ringbuffer;
usart.c:
extern volatile struct T_Ringbuffer TX_Ringbuffer;
Man kann das auch über compileranweisungen wie #ifdef #else in den
header dateien lösen. Aber ich denke mal , der weg oben ist erstmal
leichter.
main.c:
volatile struct T_Ringbuffer TX_Ringbuffer;
definiert die Struktur.
------------------------------------------------------
usart.c:
extern volatile struct T_Ringbuffer TX_Ringbuffer;
verweist den linker auf die definition in main.c
--------------------------------------------------------
arbeitet ja nun mit zwei Zeigern.
Ein Zeiger auf struct Ringbuffer und ein Zeiger auf ein stringarray.
Mit beiden Codezeilen verändere ich die Inhalte der Arrays.
Warum aber muss ich bei dem Funktionsaufruf das "normale" Array nicht
mit der Adresse ansprechen, bei dem struct jedoch schon?
struct.urschwach schrieb:> Warum aber muss ich bei dem Funktionsaufruf das "normale" Array nicht> mit der Adresse ansprechen, bei dem struct jedoch schon?
Weil Arrays anders sind.
Arrays werden niemals als Kopie übergeben, sondern immer indem die
Startadresse des Arrays übergeben wird. Steht der Name eines Arrays
alleine (d.h. ohne Indexangabe), dann ist damit immer die Adresse des
Arrays gemeint. (Einzige Ausnahme: sizeof)
Jetzt muss ich mich nochmals wundern. Sagt denn dein C-Buch darüber
nichts?
(Wenn du keines hast, dann lass dir gesagt sein: Du wirst eines
brauchen. Diese beiden Dinge hier sind die Spitze eines Eisbergs und
noch vergleichsweise simpel. Da warten noch viele Dinge auf dich, die du
lernen musst. Dein C-Buch kennt die Dinge und erklärt sie dir.)
> char* meinarray[3] = {0,2,5};
du meintest
char meinarray[3] = {0,2,5};