struct: request for member * in something not a structure or union

Gast #5607861
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?
Gast #5607887
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.
Gast #5607921
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
#5607933
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.
Gast #5608241
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
#5608446
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.
#5608461
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.
#5608485
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
}
Gast #5608495
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.
Gast #5608595
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.
#5608604
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").

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren