Forum: Mikrocontroller und Digitale Elektronik struct: request for member * in something not a structure or union


von Florian (Gast)


Lesenswert?

Hi,
ich programmiere einen Atmega in C mit AtmelStudio. beim kompilieren 
bekomme ich eine Error-Meldung, die ich nicht weiß wie ich die lösen 
kann.

Im header steht:
1
typedef struct {
2
  uint8_t  size;
3
  uint8_t  idByte[10];
4
  uint8_t  ack;
5
} Id;
6
7
Id id;

id ist ja jetzt eigentlich global. im c-file möchte ich dann die 
elemente beschreiben
1
id->size = 4;

dabei bekomme ich aber die Fehlermeldung:
request for member 'size' in something not a structure or union.

Was kann bzw. muss ich machen, damit ich die Elemente beschreiben und 
lesen kann?

von Harry L. (mysth)


Lesenswert?

1
id.size = 4;

von Stefan F. (Gast)


Lesenswert?

Wenn du "id->" schreibst, dann muss id ein Pointer auf eine Struktur 
oder ein Objekt sein. In deinem Fall ist id jedoch die 
Struktur(-Instanz) selbst.

von Florian (Gast)


Lesenswert?

Wenn ich einen Punkt machen möchte, fügt AtmelStudio automatisch einen 
Pfeil ein. Ich kann zwar dann das zeichen > mit der Backspace-Taste 
löschen und dann steht dort ein punkt, bekomme dann aber trotzdem noch 
die selbe Fehlermeldung.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Florian schrieb:
> Wenn ich einen Punkt machen möchte, fügt AtmelStudio automatisch einen
> Pfeil ein.

Das klingt kaputt.

von guest (Gast)


Lesenswert?

Florian schrieb:
> in something not a structure or union

Dann scheint der Compiler an der Stelle den Typ von 'id' nicht zu kennen
Hast Du Deinen Header auch per '#inclue' in Dein C-File eingebunden?

von Florian (Gast)


Lesenswert?

guest schrieb:
> Hast Du Deinen Header auch per '#inclue' in Dein C-File eingebunden?

Ja, das habe ich gemacht.
Habe den Fehler gefunden. beim Funktionsaufruf war id nicht typ Id, 
sondern uint8.
Trotzdem bekomme ich kein Punkt dazwischen, sondern es wird immer ein 
pfeil erzeugt

von guest (Gast)


Lesenswert?

Florian schrieb:
> Trotzdem bekomme ich kein Punkt dazwischen, sondern es wird immer ein
> pfeil erzeugt

Dann ist der Typ immer noch nicht 'Id' sondern 'Id*'.
Zeig doch mal den kompletten Code, so ist das doch nur stochern im 
Nebel.

von Harry L. (mysth)


Lesenswert?

Florian schrieb:
> guest schrieb:
>> Hast Du Deinen Header auch per '#inclue' in Dein C-File eingebunden?
>
> Ja, das habe ich gemacht.
> Habe den Fehler gefunden. beim Funktionsaufruf war id nicht typ Id,
> sondern uint8.
> Trotzdem bekomme ich kein Punkt dazwischen, sondern es wird immer ein
> pfeil erzeugt

Logisch, weil du Funktioen keine struct übergeben kannst, sondern nur 
einen Pointer auf eine struct.

Bsp:
1
void foo(Id *id)
2
{
3
  id->size = 4;
4
}
5
6
x = foo(&id);

Da ist der Pfeil korrekt.

von Frank _. (fbi)


Lesenswert?

Das 'Id id;' gehört so auch nicht in den Header sondern in ein C-File. 
Wenn überhaupt, dann steht im Header 'extern Id id;'.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Harry L. schrieb:
> Logisch, weil du Funktioen keine struct übergeben kannst, sondern nur
> einen Pointer auf eine struct.

Wie kommst du denn darauf?

von Kaj (Gast)


Lesenswert?

Harry L. schrieb:
> weil du Funktioen keine struct übergeben kannst
Das funktioniert sogar ganz wunderbar.
1
#include <inttypes.h>
2
#include <stdio.h>
3
4
5
typedef struct {
6
    uint32_t id;
7
} Id_t;
8
9
10
void foo(Id_t id);
11
12
13
int main(void)
14
{
15
    Id_t Id;
16
17
    Id.id = 42;
18
    foo(Id);
19
20
    return 0;
21
}
22
23
24
void foo(Id_t id)
25
{
26
    printf("Value of Id.id is: %" PRIu32 "\n", id.id);
27
}
1
$ gcc -std=c99 -Wall -Wextra -o main main.c && ./main
2
Value of Id.id is: 42

von Dirk B. (dirkb2)


Lesenswert?

Harry L. schrieb:
> Logisch, weil du Funktioen keine struct übergeben kannst, sondern nur
> einen Pointer auf eine struct.

Das war mal teilweise in den allerersten C Versionen so.
Auch als K&R C bekannt.

Spätestens seit 1989 ist dem nivht mehr so.

Man kann sogar komplettes structs als Rückgabewert einer Funktion 
nehmen.

von Daniel -. (root)


Lesenswert?

Grundsätzlich in header files nie Objekte erzeugen, nur deren Bauplan 
beschreiben.
Also deklarieren, nicht instanziiren. Mach dir den Unterschied klar.

von Harry L. (mysth)


Lesenswert?

Dirk B. schrieb:
> Das war mal teilweise in den allerersten C Versionen so.
> Auch als K&R C bekannt.
>
> Spätestens seit 1989 ist dem nivht mehr so.
>
> Man kann sogar komplettes structs als Rückgabewert einer Funktion
> nehmen.

Man kann nur skalare Datentypen übergeben.
Und das hat sich bei C (ohne ++) seit K&R auch nicht geändert.

von mh (Gast)


Lesenswert?

Harry L. schrieb:
> Man kann nur skalare Datentypen übergeben.
Willst du damit sagen, dass man keine Arrays übergeben kann, oder 
bezeichnest du auch Strukuren als "nicht skalar"? Weil Strukturen, um 
die es bis jetzt ging, kann man übergeben.

von Harry L. (mysth)


Lesenswert?

mh schrieb:
> Harry L. schrieb:
>> Man kann nur skalare Datentypen übergeben.
> Willst du damit sagen, dass man keine Arrays übergeben kann, oder
Richtig!
Man kann nur einen Pointer auf ein Array übergeben.

https://de.wikipedia.org/wiki/Skalare_Variable

> bezeichnest du auch Strukuren als "nicht skalar"? Weil Strukturen, um
> die es bis jetzt ging, kann man übergeben.

Falsch!
Du übergibst einen Pointer auf die Struktur.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Harry L. schrieb:
> mh schrieb:
>> Harry L. schrieb:
>>> Man kann nur skalare Datentypen übergeben.
>> Willst du damit sagen, dass man keine Arrays übergeben kann, oder
> Richtig!
> Man kann nur einen Pointer auf ein Array übergeben.

Oder einen Pointer auf dessen erstes Element.

> https://de.wikipedia.org/wiki/Skalare_Variable
>
>> bezeichnest du auch Strukuren als "nicht skalar"? Weil Strukturen, um
>> die es bis jetzt ging, kann man übergeben.
>
> Falsch!
> Du übergibst einen Pointer auf die Struktur.

Nein. Strukturen können als Parameter an Funktionen übergeben werden. 
Sie werden dann, wie skalare Typen auch, per Kopie übergeben.
Arrays können nicht übergeben werden, sondern "zerfallen" in einen 
Zeiger auf das erste Element. Indirekt könnte man ein Array übergeben, 
wenn man es zu einem Element einer Struktur macht und diese dann 
übergibt.

von Harry L. (mysth)


Lesenswert?

Rolf M. schrieb:
> Nein. Strukturen können als Parameter an Funktionen übergeben werden.
> Sie werden dann, wie skalare Typen auch, per Kopie übergeben.

Reden wir +ber dieselbe Programmiersprache?
Im Fall von C ist das schlicht falsch.

von STK500-Besitzer (Gast)


Lesenswert?

Harry L. schrieb:
> Reden wir +ber dieselbe Programmiersprache?
> Im Fall von C ist das schlicht falsch.

hmmm...
http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/015_c_strukturen_003.htm

von Rolf M. (rmagnus)


Lesenswert?

Harry L. schrieb:
> Rolf M. schrieb:
>> Nein. Strukturen können als Parameter an Funktionen übergeben werden.
>> Sie werden dann, wie skalare Typen auch, per Kopie übergeben.
>
> Reden wir +ber dieselbe Programmiersprache?
> Im Fall von C ist das schlicht falsch.

Ich weiß nicht, über welches C du sprichst, aber meine Aussage gilt für 
Standard ISO C. Ich hab auch keine Ahnung, wo du die Idee her hast, das 
sei anders.
Arrays zerfallen bei den meisten Verwendungsarten (unter anderem bei 
Übergabe an eine Funktion) in Zeiger auf deren erstes Element. Bei 
Strukturen gibt es so einen Mechanismus nicht.
Aber mal ein Beispiel.
Was denkst du, passiert bei folgendem Programm? Geht es durch den 
Compiler, und wenn ja, was gibt es aus? Probiere es auch mal aus.
1
#include <stdio.h>
2
3
struct MyStruct
4
{
5
    int a;
6
    int b;
7
};
8
9
void myfunc(struct MyStruct m)
10
{
11
    m.a = 3;
12
}
13
14
int main()
15
{
16
    struct MyStruct s = { 1, 2 };
17
    myfunc(s);
18
    printf("%d\n", s.a);
19
}

von Stefan F. (Gast)


Lesenswert?

1
stefan@stefanspc:~$ cat > test.c
2
#include <stdio.h>
3
4
struct MyStruct
5
{
6
    int a;
7
    int b;
8
};
9
10
void myfunc(struct MyStruct m)
11
{
12
    m.a = 3;
13
}
14
15
int main()
16
{
17
    struct MyStruct s = { 1, 2 };
18
    myfunc(s);
19
    printf("%d\n", s.a);
20
}
21
stefan@stefanspc:~$ gcc test.c
22
stefan@stefanspc:~$ ./a.out
23
1

m.a wurde also nur innerhalb der Funktion verändert, aber nicht im 
Hauptprogramm. Die Übergabe fand also als Kopie (by value) statt, nicht 
als Pointer.

Das hat mich jetzt nicht wirklich überrascht.

von Rolf M. (rmagnus)


Lesenswert?

Stefanus F. schrieb:
> Das hat mich jetzt nicht wirklich überrascht.

Das sollte ja auch nicht dich überraschen, sondern Harry.

von W.S. (Gast)


Lesenswert?

Florian schrieb:
> Was kann bzw. muss ich machen, damit ich die Elemente beschreiben und
> lesen kann?

Im Grunde kannst du machen was und wie du willst, denn C läßt eine 
Menge schwerverständliches Zeugs zu.

Aber raten würde ich dir dennoch zu einem anderen Stil.

Erstens: vermeide typedef, denn damit definiert man keine Typen, sondern 
führt nur eine Umbenennung aus. Normal geht das bei struct's so:
struct NameDesStrukturtyps { InhaltDesStrukturtyps };

Eine blöde Eigentümlichkeit bei C ist, daß du beim Deklarieren von 
Variablen dann immer struct davor schreiben mußt. Also
struct MeinTyp MeineVariable;
Eigentlich nur deshalb versuchen die Leute, per typedef oder #define das 
hinschreiben müssen von "struct" zu vermeiden.

Zweitens: Typen und Variablen bloß durch eine Großschreibung zu 
unterscheiden, empfinde ich als ausgemachten Bockmist. Weitaus 
deutlicher ist es, wenn man es durch einen Präfix oder Suffix 
voneinander unterscheidet. Beispiele:
Foo foo;   // schlecht.
T_foo foo; // besser
Tfoo foo;  // besser
foo_t foo; // auch besser

Drittens: Das Dranhängen des Asterisks an den Variablenbezeichner 
empfinde ich als üble Zumutung. Schließlich ist es eine Typeigenschaft 
und nicht eine Eigenschaft des Variablennamens. Also:
int *blabla; // finde ich miserabel
int* blabla; // ist besser, weil sinnfälliger

Aber da machen die C-Leute genauso wie die Linux/Unix-Leute traditionell 
gerne die allerübelsten Schnitzer, z.B. einen führenden Punkt im 
Dateinamen als Platz für ein Flag (hidden oder nicht). Was hat ein Flag 
in einem Namen zu suchen? Sowas ist eine Obliegenheit des Dateisystems, 
aber nicht des Dateinamens.

W.S.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Aber da machen die C-Leute genauso wie die Linux/Unix-Leute traditionell
> gerne die allerübelsten Schnitzer, z.B. einen führenden Punkt im
> Dateinamen als Platz für ein Flag (hidden oder nicht).

Es ist eigentlich kein Flag, sondern einfach eine Konvention. Dateien, 
deren Namen mit einem Punkt beginnen, werden beim Auflisten ausgelassen.

> Was hat ein Flag in einem Namen zu suchen?

Genauso viel, wie das Flag, das angibt, ob die Datei ausgeführt werden 
kann ("blah.exe").

von Jemand (Gast)


Lesenswert?

W.S. schrieb:
> int* blabla; // ist besser, weil sinnfälliger

Miserabel, weil int* a, b; eben keine zwei Pointer deklariert.

von W.S. (Gast)


Lesenswert?

Jemand schrieb:
> Miserabel, weil int* a, b; eben keine zwei Pointer deklariert.

Das ist klar, aber das ist einer der vielen Geburtsfehler von C - den 
man aber problemlos handhaben kann, indem man Variablen einzeln 
deklariert.

W.S.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.