Forum: Mikrocontroller und Digitale Elektronik adresse von Struktur aus anderer C-Datei bekommen


von Chandler B. (chandler)


Lesenswert?

Hallo,
ich habe ein Problem, wo ich nicht weiterkomme und erhoffe mir hier um 
etwas hilfe.

Ich habe in src1.h eine Struktur deklariert. In src1.c wird diese 
definiert und damit gearbeitet.
in src2.c habe ich src1.h inkludiert, damit ich die Struktur kenne.
In src2.c habe ich einen Pointer der struktur erstellt. Ich möchte 
gerne, dass dieser auf die Struktur in src1.c zeigt, sodass wenn ich in 
src2.c daten darin ändere, diese in src1.c geändert sind.

src1.h
1
typedef struct
2
{
3
  uint8 x;
4
} Name_ts;
src1.c
1
Name_ts name_s;
2
3
...
4
void getStructAddress(Name_ts** name_pps)
5
{
6
  if (NULL != name_pps)
7
  {
8
    name_pps = &name_s;
9
  }
10
}
src2.c
1
#include "src1.h"
2
...
3
4
Name_ts* name_ps;
5
...
6
...
7
8
getStructAddress(name_ps)

aber nach aufruf der Funktion getStructAddress ist die adresse von 
name_ps immer noch 0.

von Wilhelm M. (wimalopaan)


Lesenswert?

Bist Du sicher, dass das ohne Warnungen kompiliert? Du hast einen 
Typ-Mismatch. Schau dir nochmal das Argument an, was Du der Funktion 
übergibst.

von Maik H. (maik_h367)


Lesenswert?

Du musst die Variable name_s in src2.c oder global bekannt machen. Am 
einfachsten geht das in src1.h mit der Deklaration:

extern Name_ts name_s;

von Yalu X. (yalu) (Moderator)


Lesenswert?

Maik H. schrieb:
> extern Name_ts name_s;

Das ist im konkreten Fall nicht nötig, aber Wilhelms Einwand ist
richtig.

Der Compiler sollte eigentlich mehrere Warnungen ausgeben, weil
verschiedene Zeigertypen wild durcheinandergeschmissen werden, es sei
denn die Warnungen sind alle deaktiviert worden.

Geht es um Arduino?

von Chandler B. (chandler)


Lesenswert?

Wilhelm M. schrieb:
> Bist Du sicher, dass das ohne Warnungen kompiliert? Du hast einen
> Typ-Mismatch. Schau dir nochmal das Argument an, was Du der Funktion
> übergibst.

Ja, da hast du recht gehabt.

src2.c
1
Name_ts* name_ps;
2
...
3
getStructAddress(&name_ps)

src1.c
1
void getStructAddress(Name_ts** name_pps)
2
{
3
  if (NULL != name_pps)
4
  {
5
    *name_pps = &name_s;
6
  }
7
}

von Wilhelm M. (wimalopaan)


Lesenswert?

Und Warnungen gab es kein? Wohl kaum ...

Das ganze sieht ja auch mehr nach Übungsaufgabe aus. Deswegen will ich 
auch einmal grundsätzlich die Frage stellen, was die Semantik der 
Funktion getStructAddress() sein soll.

Gehört NULL tatsächlich zum zugelassenen Wertebereich des Paraameters 
name_pps? Falls ja, dann ist alles ok. Falls nein, d.h. es ist ein 
Fehler des Programmierers, jemals diese Funktion mit NULL aufzurufen, 
dann ist das if-statement falsch, und es gehört dort eine Zusicherung 
hin.

Besprich das mal mit Deinem Lehrer ...

von Adam P. (adamap)


Lesenswert?

Gibt es einen Grund warum du es nicht einfach so schreibst?
Oder möchtest du unbedingt den Pointer übergeben?
1
Name_ts* getStructAddress(void)
2
{
3
    return &src1_name;
4
}
5
...
6
7
Name_ts* name_ps;
8
9
name_ps = getStructAddress();

von Joh S. (joh93)


Lesenswert?

Das wäre meine implementierung, wenn man mit den Pointern so arbeiten 
will ;)

src1.h
1
typedef struct
2
{
3
  uint8 x;
4
} Name_ts;
5
6
extern void getStructAddress(Name_ts* name_pps);

src1.c
1
#include "src1.h"
2
3
static Name_ts name_s;
4
5
void getStructAddress(Name_ts* name_pps)
6
{
7
  // mal weggelassen, da wenn der Zeiger nicht initialisiert ist irgendwas drinsteht.
8
  //if (NULL != name_pps)
9
  //{
10
    name_pps = &name_s;
11
  //}
12
}
src2.c
1
#include "src1.h"
2
3
Name_ts* name_ps;
4
getStructAddress(name_ps);

Wo man sich jetzt noch streiten könnte, ob man die Adresse als return 
wert zurückgibt oder über einen Parameter ist die Frage. Kann man machen 
wie man will... Das meiste optimiert sowiso der Compiler weg. Bei guter 
Optimierung wird die Funktion sowiso direkt durch die Adresse ersetzt.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Joh S. schrieb:
> Das wäre meine implementierung, wenn man mit den Pointern so arbeiten
> will ;)
> ...

Das ist doch fast der gleiche Code wie der des TE, nur dass du zu den
zwei Fehlern des Originals noch einen dritten hinzugefügt hast.

von Peter D. (peda)


Lesenswert?

Man muß Pointer nicht von hinten durch die Brust ins Auge über Pointer 
auf Pointer auslesen. Pointer darf man auch als Returnwert zurückgeben.

von Joh S. (joh93)


Lesenswert?

Yalu X. schrieb:
> Joh S. schrieb:
>> Das wäre meine implementierung, wenn man mit den Pointern so arbeiten
>> will ;)
>> ...
>
> Das ist doch fast der gleiche Code wie der des TE, nur dass du zu den
> zwei Fehlern des Originals noch einen dritten hinzugefügt hast.

Wo sollen da 3 Fehler drin sein? Compiliert einwandfrei.
Ja es ist fast der gleiche Code. Die Frage war ja, was man ändern muss, 
damit der Code funktioniert.

Ob man jetzt einen Pointer übergibt oder als return Wert liefert ist 
meiner Meinung nach total egal. Im AutoSAR kontext ist sowas normal, da 
immer ein Std_ReturnType mit E_OK oder E_NOT_OK zurückgeliefert wird ...

von Obelix X. (obelix)


Lesenswert?

Der TO wollte es wahrscheinlich in etwa so machen : (es hat nix mit der 
Aufteilung auf mehrere Dateien zu tun)
1
#include <stdio.h>
2
#include <stdint.h>
3
4
typedef struct{
5
  uint8_t x;
6
} Name_ts;
7
8
Name_ts name_s;
9
Name_ts* name_ps;
10
11
void getStructAddress(Name_ts** name_pps) {
12
  if (NULL != name_pps) {
13
    *name_pps = &name_s;
14
  }
15
}
16
17
int main() {
18
  printf("Hello, World!\n");
19
  printf("%8p\n",&name_s);
20
  getStructAddress(&name_ps);
21
  printf("%8p\n",name_ps);
22
  return 0;
23
}

Es fehlen ein paar entscheidende '*' bzw. '&'.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Joh S. schrieb:
> Wo sollen da 3 Fehler drin sein? Compiliert einwandfrei.

Ja, die Warnungen sind weg (wenn man die fehlende Deklaration von uint8
noch hinzufügt).

> Ja es ist fast der gleiche Code. Die Frage war ja, was man ändern muss,
> damit der Code funktioniert.

Keine Warnungen und funktionieren sind zweierlei Dinge. Hast du deinen
Code mal getestet?

von Joh S. (joh93)


Angehängte Dateien:

Lesenswert?

Yalu X. schrieb:
> Joh S. schrieb:
>> Wo sollen da 3 Fehler drin sein? Compiliert einwandfrei.
>
> Ja, die Warnungen sind weg (wenn man die fehlende Deklaration von uint8
> noch hinzufügt).
>
>> Ja es ist fast der gleiche Code. Die Frage war ja, was man ändern muss,
>> damit der Code funktioniert.
>
> Keine Warnungen und funktionieren sind zweierlei Dinge. Hast du deinen
> Code mal getestet?

da war es anscheinend noch zu früh... Ist natürlich dumm, wenn man eine 
kopie des zeigers übergibt...

Somit schließe ich mich der allgemeinen meinung an, dass der Zeiger auf 
die Instanz als return-Wert am sinnvollsten wäre.

: Bearbeitet durch User
von Obelix X. (obelix)


Lesenswert?

Joh S. schrieb:
> Somit schließe ich mich der allgemeinen meinung an, dass der Zeiger auf
> die Instanz als return-Wert am sinnvollsten wäre.

Der TO hat ja nur einen Testcode geliefert. Was also wenn die Funktion 
so aus sieht :
1
uint8_t getStructAddress(Name_ts** name_pps) {
2
  if (NULL != name_pps) {
3
    *name_pps = &name_s;
4
    return 0;
5
  }
6
  return -1;
7
}

von Wilhelm M. (wimalopaan)


Lesenswert?

Joh S. schrieb:
> Wo man sich jetzt noch streiten könnte, ob man die Adresse als return
> wert zurückgibt oder über einen Parameter ist die Frage. Kann man machen
> wie man will...

In diesem Fall ist die Signatur eindeutig: ein pointer-to-non-const ist 
immer ein Output-Parameter.

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.