Forum: Compiler & IDEs Zeiger auf ein Struct-Array-Element übergeben


von Jannik (Gast)


Lesenswert?

Guten Abend zusammen.

Ich habe mal eine kleine Frage bezüglich "Zeiger auf ein 
Struct-Array-Element".
1
typedef struct {
2
  char nachricht[max_nachrichtenlaenge];
3
  uint8_t empfaenger_nr[max_teilnehmer];
4
  } MELDUNG;
5
6
MELDUNG a[5];
7
MELDUNG b[5];
8
MELDUNG c[5];

anschließend übergebe ich ein struct vom Typ MELDUNG an eine Funktion 
(diese ist auf das Nötigste reduziert).
1
int create(MELDUNG* event){
2
  uint8_t i = 0;
3
  uint8_t zeile = 0;
4
  uint8_t empfaenger_id;
5
  
6
  while (strcmp(*event[i].nachricht,"") != 0){
7
    strcpy(sendeliste[zeile].nachricht, *event[i].nachricht); //Funktioniert
8
    empfaenger_id = *event[i].empfaenger_nr[i]; //Funktioniert nicht -> invalid type of unaray '*'(have 'int')
9
    i++;
10
  }
11
12
return 1;
13
}

Wieso kann ich nicht auf das Element im empfaenger_nr Array zugreifen? 
empfaenger_id habe ich auch schon als typ int probiert. Ebenfalls 
erfolglos.

Bin für jeden Tip dankbar.

Gruß
Jannik

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jannik schrieb:

>     empfaenger_id = *event[i].empfaenger_nr[i]; //Funktioniert nicht ->

event[i] ist ein MELDUNG, kein MELDUNG*.  Daher ist 
event[i].empfaenger_nr[i] ein uint8_t und kein uint8_t*, kann mithin 
nicht dereferenziert werden.

von Jannik (Gast)


Lesenswert?

Danke.
Ich habe einen Verdacht, jedoch verstehe ich es noch nicht ganz.
D.h. also ich mache auch *event[i], event[i]? Der Compiler akzeptiert 
das.

Aber wieso funktioniert es bei *event[i].nachricht ? Kann mir das 
nochmal wer näher erläutern?

von Andreas W. (geier99)


Lesenswert?

Jannik schrieb:
> Aber wieso funktioniert es bei *event[i].nachricht ? Kann mir das
> nochmal wer näher erläutern?

weil die Array Variable "nachricht"  ein  Pointer ist.

von Jannik (Gast)


Lesenswert?

Ahhh okay ...und auf das erste Zeichen des Char-Arrays zeigt?
Vielen Dank

von Andreas W. (geier99)


Lesenswert?

Jannik schrieb:
> Ahhh okay ...und auf das erste Zeichen des Char-Arrays zeigt?
> Vielen Dank

ja, genauso ist es.  Bitte!

von Hans (Gast)


Lesenswert?

Bist Du Dir sicher, dass das funktioniert und keine Warnung gibt?
1
strcpy(sendeliste[zeile].nachricht, *event[i].nachricht); //Funktioniert

strcpy möchte ja einen Zeiger, und event[i].nachricht zeigt auf das 
erste Element im Array. Wenn Du es noch derefenzierst, ist es kein 
Zeiger mehr.

von Rolf Magnus (Gast)


Lesenswert?

Jannik schrieb:
> Aber wieso funktioniert es bei *event[i].nachricht ? Kann mir das
> nochmal wer näher erläutern?

Was verstehst du unter "funktioniert"? Ich kann mir nicht so recht 
vorstellen, das es das tut.

Hans schrieb:
> Wenn Du es noch derefenzierst, ist es kein Zeiger mehr.

Ebenth.

von Jannik (Gast)


Lesenswert?

Ihr habt recht. Ich habe die Warnung des Compilers übersehen!

Mit funktioniert meinte ich lediglich "ohne Error".

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Andreas W. schrieb:

> weil die Array Variable "nachricht" ein  Pointer ist.

Nein.  Ein Array ist ein Array und ein Pointer ist ein Pointer.

Nur weil sie in der Verwendung teilweise ähnlich sind, sind Arrays noch 
lange keine Pointer — ausser bei Funktionsparametern, wo es tatsächlich 
das "Array decays to Pointer" gibt.

Bei Zeigern, int und double gilt ja auch: Nur weil man sie subtrahieren 
kann, vergleichen kann oder einen int draufaddieren kann, sind Zeiger, 
int und double noch lange nicht das selbe.

von Andreas W. (geier99)


Lesenswert?

Johann L. schrieb:
> Andreas W. schrieb:
>
>> weil die Array Variable "nachricht" ein  Pointer ist.

das weis ich auch, ich hätte wohl besser schreiben sollen:

Der Name eines Arrays kann als Pointer auf sein erstes Element benutzt 
werden.

von Karl H. (kbuchegg)


Lesenswert?

Andreas W. schrieb:

> Der Name eines Arrays kann als Pointer auf sein erstes Element benutzt
> werden.

Besser. Viel besser.

Das Problem mit deiner Aussage ist, dass die Kenner zwar wissen was du 
meinst, aber Anfänger ganz gerne die Aussage missverstehen.

So, so. Der Arrayname ist ein Pointer. Warum geht dann das nicht

FileA.C
1
int Werte[20];

FileB.C
1
extern int *Werte;
2
3
void foo()
4
{
5
  Werte[5] = 26;
6
}

wo doch ein Array ein Pointer ist?

von Rolf Magnus (Gast)


Lesenswert?

Johann L. schrieb:
> Nur weil sie in der Verwendung teilweise ähnlich sind, sind Arrays noch
> lange keine Pointer — ausser bei Funktionsparametern, wo es tatsächlich
> das "Array decays to Pointer" gibt.

Eigentlich gibt es das nicht nur dort, sondern fast überall. Auch z.B. 
der Dereferenzierungs-Operator kann ja auf Arrays angewendet werden. 
Selbst die Index-Operation x[n] ist auch nur definiert als äquivalent zu 
*(x+n).
Aber leider ist eben trotzdem nur fast überall, und die Unterscheidung 
ist sehr wichtig.

Karl Heinz Buchegger schrieb:
> So, so. Der Arrayname ist ein Pointer. Warum geht dann das nicht

Naja, der Klassiker ist doch eher sowas wie:
1
void funktion(char arr[])
2
{
3
    for (size_t i = 0; i < sizeof arr; i++)
4
    {
5
        putchar(arr[i]);
6
    }
7
}

mit einer Frage wie: "Warum werden hier nur die ersten vier Zeichen 
ausgegeben?"

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:

> Naja, der Klassiker ist doch eher sowas wie:

:-)
Diese Syntax kannte ich damals noch nicht, als ich für mich die 
Unterscheidung Array-Pointer entdeckte und mir einen Reim darauf machen 
musste. Das globale Array/Pointer Beispiel hat mir dann die Augen 
geöffnet, als ich dann endlich verstanden hatte, was ich im K&R 
misverstanden habe.

Drum bringe ich es ganz gerne.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn man mit dem Extern/Pointer/Array-Beispiel von Karl Heinz auf die
Nase gefallen ist, lernt man dann meistens auch, warum alles Gobale in
Header-Files deklariert gehört und diese insbesondere auch dort
inkludiert werden sollten, wo die Definitionen der entsprechenden
Variablen bzw. Funktionen stehen. Dann wird man vom Compiler nämlich
durch ein "error: conflicting types" auf den Fehler hingewiesen.

Neben den Extern-Deklarationen und dem Sizeof-Operator ist die
Unterscheidung zwischen Array und Pointer bei der Behandlung von Arrays
von Arrays (im Volksmund auch mehrdimensionale Arrays genannt) von
Bedeutung. Da stößt man dann plötzlich auf so seltsame Dinge wie Pointer
auf Arrays. Auch zu diesem Aspekt gab es hier im Forum schon genügend
Verwirrung.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Oder:

FileA.C
1
int Werte[20];

FileB.C
1
extern int *Werte;
2
3
void foo (int *w)
4
{
5
  Werte = w;
6
}

wo doch ein Array ein Pointer ist?

Oder:

FileA.C
1
int Werte[20];

FileB.C
1
extern int *Werte;
2
3
unsigned char foo (void)
4
{
5
  unsigned char x;
6
  asm ("ldi %0, lo8(%1)" : "=r" (x) : "i" (Werte));
7
  return x;
8
}

von Rolf Magnus (Gast)


Lesenswert?

Yalu X. schrieb:
> Neben den Extern-Deklarationen und dem Sizeof-Operator ist die
> Unterscheidung zwischen Array und Pointer bei der Behandlung von Arrays
> von Arrays (im Volksmund auch mehrdimensionale Arrays genannt) von
> Bedeutung. Da stößt man dann plötzlich auf so seltsame Dinge wie Pointer
> auf Arrays. Auch zu diesem Aspekt gab es hier im Forum schon genügend
> Verwirrung.

Man muß halt erkennen, daß aus einem Array bei den meisten Operationen 
ein Pointer auf das erste Element gemacht werden kann. Bei einem Array 
aus Arrays ist das erste Element eben ein Array. Es wird nicht rekursiv 
durchgegangen und aus dem Array aus Arrays ein Pointer auf das Erste 
Element eines Arrays aus Pointern. Spaßig wird das, wenn man versucht, 
mehrdimensionale Arrays an Funktionen zu übergeben.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:

> Spaßig wird das, wenn man versucht, mehrdimensionale Arrays an
> Funktionen zu übergeben.

Wo ist das Problem?
1
char get_a (char a[][8])
2
{
3
    return a[2][1];
4
}

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.