Forum: Compiler & IDEs Pointer auf Array in struct, aber wie macht man das?


von Steffen H. (avrsteffen)


Lesenswert?

Hallo,

Ich komm einfach nicht weiter mit einem Pointer auf ein Array-Eintrag in 
einem struct namens settings_t. Ich habe eine Funktion, die mir die 
Daten aus dem Array im struct per SPI ausgeben soll. Und die erwartet 
einen Pointer auf den Beginn der Daten im Array des Structs.

Hier ist das Struct:
1
typedef struct {
2
  double steps_per_mm[3];
3
  uint8_t microsteps;
4
  uint8_t pulse_microseconds;
5
  double default_feed_rate;
6
  double default_seek_rate;
7
  uint8_t invert_mask;
8
  double mm_per_arc_segment;
9
  double acceleration;
10
  double junction_deviation;
11
  long DRVCTRL[3];
12
  long CHOPCONF[3];
13
  long SMARTEN[3];
14
  long SGCSCONF[3];
15
  long DRVCONF[3];
16
} settings_t;
17
18
extern settings_t settings;

Hier die Funktion welche den Pointer erwartet.
1
void spi_write_data(char* source, char wr_bytes, char spi_cs)

Und so versuche ich sie momentan aufzurufen:
1
spi_write_data(&settings.DRVCONF[0],5,CS_EXT);

Ich weiß das da irgendwas noch nicht stimmt, denn es kommt immer die 
Warmung:
1
../spi.c:68: warning: passing argument 1 of 'spi_write_data' from incompatible pointer type

Wie deklariere/initialisiere ich den Pointer richtig? Bekomm es einfach 
nicht hin. Ich lerne leider erst in "C" zu programmieren.

Wer kann mir weiterhelfen?

Steffen

von geier99 (Gast)


Lesenswert?

Steffen H. schrieb:
> void spi_write_data(char* source, char wr_bytes, char spi_cs)

wie wärs mit:
void spi_write_data(long* source, char wr_bytes, char spi_cs)

von Sebasrian L. (Gast)


Lesenswert?

DRVCONF ist ein long array deine funktion erwartet aber nen char 
pointer. Typkonflikt?

von Karl H. (kbuchegg)


Lesenswert?

Steffen H. schrieb:

> Ich weiß das da irgendwas noch nicht stimmt, denn es kommt immer die
> Warmung:
>
1
> ../spi.c:68: warning: passing argument 1 of 'spi_write_data' from
2
> incompatible pointer type
3
>

spi_write_data will einen Pointer auf char.
Du gibst ihm einen Pointer auf long.

und das passt nun mal nicht. ein char ist kein long. Und auch ein 
Pointer auf char ist daher erst mal nicht kompatibel mit einem Pointer 
auf long.

Jetzt wissen wir an dieser Stelle aber, das dieses 'char' im Grund nur 
ein notwendiges Übel ist für 'ist mir eigentlich wurst was du hast, ich 
nehm einfach die Bytes und schreib sie'.

D.h. im Grunde spielt es keine wirkliche Rolle, dass da ein long im 
Spiel ist. Man darf hier also durchaus Umcasten.
Man muss nur darauf achten, dass spi_write_data auch die tatsächlich 
richtige Anzahl an Bytes schreibt. Und an dieser Stelle kommt dann eine 
zweite Zutat ins Spiel: ein sizeof.

um das komplette Array zu schreiben.
1
  spi_write_data( (char*)settings.DRVCONF, sizeof( settings.DRVCONF ), CS_EXT);

von Steffen H. (avrsteffen)


Lesenswert?

Wow, das geht aber noch schnell um diese Urzeit. Danke schon mal für die 
Antworten.

geier99 schrieb:
> wie wärs mit:
> void spi_write_data(long* source, char wr_bytes, char spi_cs)
Ich will die Funktion schon multikunktionell halten. Deswegen möcht ich 
'char' wenn möglich nicht unbedingt mit 'long' ersetzen.

Karl Heinz Buchegger schrieb:
> um das komplette Array zu schreiben.
1
spi_write_data( (char*)settings.DRVCONF, sizeof( settings.DRVCONF ), CS_EXT);
Ich werd es sofort ausprobieren. Das mit dem 'sizeof' wollte ich auch 
noch machen wenn es erstmal funktioniert.

Danke euch allen schon mal.

Steffen

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Steffen H. schrieb:

> geier99 schrieb:
>> wie wärs mit:
>> void spi_write_data(long* source, char wr_bytes, char spi_cs)
> Ich will die Funktion schon multikunktionell halten. Deswegen möcht ich
> 'char' wenn möglich nicht unbedingt mit 'long' ersetzen.

char* durch long* ist zudem eine gaaanz schlechte Idee wenn bestimmte 
ALignments gegeben sind, etw wenn dein Code auf ARM oder PowerPC oder 
einer anderen strict-Alignment Plattform ausführt.  Zur Hardware steht 
ja nix geschrieben (ausser in deinem Login-Name).

Zudem ist das Layout von settings_t eigenwillig.  Erwarte Probleme beim 
Übertragen zwischen Plattformen mit unterschiedlichen Alignments, 
zumindest wenn du settings_t als ganzes überträgst.

Ohne saubere (De)Serialisierung sind Bit-, Byte-, Word- und 
float-Endianess sowie Darstellung von Flotings weitere Problemfelder.

von Steffen H. (avrsteffen)


Lesenswert?

Johann L. schrieb:
> char* durch long* ist zudem eine gaaanz schlechte Idee wenn bestimmte
> ALignments gegeben sind, etw wenn dein Code auf ARM oder PowerPC oder
> einer anderen strict-Alignment Plattform ausführt.  Zur Hardware steht
> ja nix geschrieben (ausser in deinem Login-Name).
>
> Zudem ist das Layout von settings_t eigenwillig.  Erwarte Probleme beim
> Übertragen zwischen Plattformen mit unterschiedlichen Alignments,
> zumindest wenn du settings_t als ganzes überträgst.
>
> Ohne saubere (De)Serialisierung sind Bit-, Byte-, Word- und
> float-Endianess sowie Darstellung von Flotings weitere Problemfelder.

Da hast du wohl Recht und ich noch garnicht drüber nachgedacht. Dann 
werd ich da wohl noch Probleme kriegen.
Danke Johann für die Hinweise.

Karl Heinz Buchegger schrieb:
> um das komplette Array zu schreiben.
1
spi_write_data( (char*)settings.DRVCONF, sizeof( settings.DRVCONF ), CS_EXT);
Es gibt leider weiterhin eine Warnung und der Pointer ist leider immer 
noch falsch. :(
Vieleicht noch das '&' vergessen und siehe da, so geht es jetzt. Ganz 
ohne WARNING. :)
1
spi_write_data((char*)&settings.DRVCONF[Motor_X],sizeof(settings.DRVCONF[Motor_X]),CS_EXT);

Danke euch allen denn jetzt kann ich endlich schlafen.

Steffen

von Rolf Magnus (Gast)


Lesenswert?

Steffen H. schrieb:
> geier99 schrieb:
>> wie wärs mit:
>> void spi_write_data(long* source, char wr_bytes, char spi_cs)
> Ich will die Funktion schon multikunktionell halten. Deswegen möcht ich
> 'char' wenn möglich nicht unbedingt mit 'long' ersetzen.

Warum nimmst du dann nicht void*? Das ist der in C als generischer 
"Zeiger auf irgendwas, dessen Typ unbekannt ist" vorgesehene Typ. Dann 
kannst du dir auch den Cast sparen.

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.