Forum: Compiler & IDEs struct probleme


von Elektro Gandalf (Gast)


Lesenswert?

Hallo,

habe mal wieder ein Problem!
Folgendes habe ich Programmiert (nur mal so zum Test):
1
struct daten
2
{
3
  uint8_t datum1;
4
  uint8_t datum2;  
5
  uint8_t datum3;
6
};
7
8
9
typedef struct daten  RSD;
10
typedef RSD* PRSD;
11
12
13
void bearbeitedaten(PRSD myrs232daten);
14
15
16
int main(void) 
17
{ 
18
  PRSD myrs232daten;
19
20
  bearbeitedaten(&myrs232daten);
21
22
}
23
24
void bearbeitedaten(PRSD myrs232daten)
25
{
26
  myrs232daten->datum1 = 1;
27
  myrs232daten->datum2 = 2;
28
  myrs232daten->datum3 = 3;
29
}

das Programm funktioniert der Compiler (GCC-Version: 4.1.1 (WinAVR 
20070122))
bringt mir jedoch folgende Warnung:

main.c:68: warning: passing argument 1 of 'bearbeitedaten' from 
incompatible pointer type

Was mache ich falsch?

von Hartmut S. (hsemken)


Lesenswert?

  PRSD myrs232daten;
  char c;

damit ist das Symbol myrs232daten ein Pointer (auf ein struct) und c ist 
ein char.

&c ist dann ein Pointer, nämlich einer, der auf ein char namens c zeigt.
Was ist dann wohl &myrs232daten?

Richtig: der alte MacOS-Programmierer würde sagen: ein Handle. Ein 
Pointer auf einen Pointer auf ein struct.

Ein Pointer auf ein struct und ein Pointer auf einen Pointer sind beides 
Pointer, aber eben nicht kompatible Typen.

Allerdings kann ich mir kaum vorstellen, dass das Programm funktioniert.
Ich würde empfehlen, das mal im Debugger genauer anzusehen und für die 
diversen verschiedenen Objekte die Adressen zu ermitteln.

Man korrigiere mich, wenn mich mein angerostetes C hier täuscht :-)

Gruß
hase

von Karl H. (kbuchegg)


Lesenswert?

Elektro Gandalf wrote:
> Hallo,
>
>
1
> struct daten
2
> {
3
>   uint8_t datum1;
4
>   uint8_t datum2;
5
>   uint8_t datum3;
6
> };
7
> 
8
> 
9
> typedef struct daten  RSD;
10
> typedef RSD* PRSD;
11
> 
12
> 
13
> void bearbeitedaten(PRSD myrs232daten);
14
> 
15
> 
16
> int main(void)
17
> {
18
>   PRSD myrs232daten;
19
> 
20
>   bearbeitedaten(&myrs232daten);
21
> 
22
> }
23
> 
24
> void bearbeitedaten(PRSD myrs232daten)
25
> {
26
>   myrs232daten->datum1 = 1;
27
>   myrs232daten->datum2 = 2;
28
>   myrs232daten->datum3 = 3;
29
> }
30
> 
31
> 
32
>
>
> das Programm funktioniert

Das wage ich zu bezweifeln.
Es mag so aussehen, aber es hat definitiv einen schwerwiegenden
Bug (oder aber du hast das Programm hier neu eingetippt und
das Programm das du compilierst ist ein anderes als das welches
du hier gepostet hast).

int main(void)
{
  PRSD myrs232daten;

  bearbeitedaten(&myrs232daten);

myrs232daten ist vom Typ PRSD, welcher seinerseit ein RSD*,
also bereits ein Pointer auf struct daten ist.

&myrs232daten hat daher den Datentyp struct daten**
und da die Funktion bearbeitedaten einen struct daten* haben
will, müsste der Compiler eigentlich anmerken, dass du hier
einen Datentyp-mismatch hast.


Ich weiss, dass jeder C Programmierer irgendwann die Phase
durchmacht, in der er denkt, dass ein typedef ala

typedef RSD* PRSD;

eine gute Idee ist. Sie ist es selten und die meisten Programmierer
hören nach kurzer Zeit wieder damit auf. Einen * im tatsächlichen
Source Code zu haben, ist weit weniger schlimm, als sich ständig
merken zu müssen, welcher typedef nun für einen Pointer und welcher
nur für eine Struktur steht (selbst wenn man den typedef Namen
mit einem P einleitet, oder wie andere es machen den Namen mit
_P beendet [ typedef struct daten RSD_P ])

int main(void)
{
  RSD myrs232daten;

  bearbeitedaten(&myrs232daten);
}

void bearbeitedaten(RSD * myrs232daten)
{
  myrs232daten->datum1 = 1;
  myrs232daten->datum2 = 2;
  myrs232daten->datum3 = 3;
}

Wenn du dich daran erinnern willst, das das was du hast
ein Pointer ist, dann ist eine beliebte Methode, den Variablen-
namen mit einem p beginnen zu lassen und den Rest mittels
Camel-Case in Gross-Kleinschreibung lesbarer zu machen:

void bearbeiteDaten(RSD * pDaten)
{
  pDaten->datum1 = 1;
  pDaten->datum2 = 2;
  pDaten->datum3 = 3;
}

von Oliver (Gast)


Lesenswert?

So ist es.

bearbeitedaten(PRSD myrs232daten) möchte einen pointer auf dein struct 
als Parameter haben, mit

PRSD myrs232daten;
bearbeitedaten(&myrs232daten);

übergibst du einen Pointer auf einen Pointer. Das geht gründlich schief.

Das Problem kommt daher, daß du deinen Variablen und Typen nicht ansehen 
kannst, ob sie nun Daten oder Pointer sind. Entweder lässt du den 
Quatsch mit dem "typedef PSRD", oder du nennst myrs232daten z.B. 
p_myrs232daten. Denn das ist ein pointer, und kein Datenfeld.

Und dann erkennst du auch, warum dein Programm auch mit dem 
warnungsfreien Aufruf

bearbeitedaten(myrs232daten);

gnadenlos abstürzen wird.

Oliver

von Elektro Gandalf (Gast)


Lesenswert?

OK danke mal!

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.