Hallo zusammen,
ich versuche inerhalb einer Funktion den Inhalt eines Arrays mit fester
Länge das per typedef definiert wurde zu ändern. Hier das vereinfachte
Problem:
Max schrieb:> typedef uint16_t AT_eightWords[8];> void Update(AT_eightWords * eW)
Das ist quasi ein Pointer auf ein Array, also ptr auf ptr.
Vermutlich willst Du nur ein Array, dann lass das * vor eW weg.
Walter T. schrieb:> Ich habe das ungewöhnliche Typedef übersehen.
Der dürfte auch das problem sein. Das wäre dann ja quasi sowas hier und
das passt nicht wirklich:
A. S. schrieb:> Max schrieb:>> typedef uint16_t AT_eightWords[8];>> void Update(AT_eightWords * eW)>> Das ist quasi ein Pointer auf ein Array, also ptr auf ptr.
Ein Pointer auf ein Array ja, aber kein Pointer auf einen Pointer.
> Vermutlich willst Du nur ein Array, dann lass das * vor eW weg.
Generell würde ich typedefs für Arrays vermeiden, weil das nur
Verwirrung stiftet.
Irgend W. schrieb:> Das wäre dann ja quasi sowas hier und> das passt nicht wirklich:> void Update(uint16_t[8] * eW)
Genauer:
rmagnus schrieb:
> Generell würde ich typedefs für Arrays vermeiden, weil das nur> Verwirrung stiftet.
In der Tat. Eine Variable solchen Typs zu übergeben sieht aus wie ein
"call by value" ist aber tatsächlich ein "call by reference". D.h.,
ohne die Definition des Types zu kennen (die Definition der Variable
reicht nicht!), kann man nicht erkennen, was der Code macht.
Ändere die Update(AT_eightWords *eW) zu
Zu Update(uint8_t *eW)
Dein Datentyp ist ein 8 Felder großes Array
davon machst du einen Pointer *eW und willst ihn so behandeln als wäre
er ein einfacher Pointer. Ich denke das geht schief. In der Update ()
brauchst du eigentlich nur einen einfachen uint8_t Pointer.
Max schrieb:> *(eW+0) = 42;
Müsste das bei *eW+0 nicht mit void Update(AT_eightWords **eW)
kombiniert werden?
Dann muss man aber die Klammern rausnehmen.
Oliver S. schrieb:> Erst sagen, was da raus kommt, dann ausprobieren.
Die Größe des Arrays. Es ist aber egal, was da herauskommt.
Ein Array und ein Pointer sind bei einer Übergabe äquivalent.
Wenn der TO sich dessen klar wird, kann er auch herausklamüsern, was da
passiert. Und ja, je nach Konstrukt was anderes. Beim TO
Max schrieb:> *eW[0] = 42;> *eW[1] = 43;> *eW[2] = 44;> *eW[3] = 45;
ist halt nur der erste Zugriff OK, der zweite zeigt auf Element 0 im
Array dahinter (also nicht nächstes Element, sondern 8 Elemente, also
außerhalb es eigentlichen Arrays.
Wenn er nicht nur "quasi" wie ich schrieb, sondern echt einen Ptr auf
Ptr übergeben hätte, dann wäre auch der erste Zugriff OK, aber danach
würde er die nächsten X Bytes als neuen Ptr interpretieren.
Egal. Den Mechnismus des TO habe ich erklärt, die Unterschiede zwischen
Ptr und Array bei der Übergabe mögen Korinthen** unter sich ausmachen.
A. S. schrieb:> Oliver S. schrieb:>> Erst sagen, was da raus kommt, dann ausprobieren.>> Die Größe des Arrays. Es ist aber egal, was da herauskommt.
Das ist nicht egal. Wäre es ein Pointer auf einen Pointer, dann käme da
eben nicht die Größe des Arrays raus.
> Ein Array und ein Pointer sind bei einer Übergabe äquivalent.
Naja, es kommt in der Funktion ein Pointer auf das erste Element an. Das
Array "zefällt" zu einem Pointer. Aber das gilt nicht rekursiv. Ein
Pointer auf ein Array bleibt auch nach Übergabe ein solcher und zerfällt
nicht zu einem Pointer auf einen Pointer.
> Egal. Den Mechnismus des TO habe ich erklärt, die Unterschiede zwischen> Ptr und Array bei der Übergabe mögen Korinthen** unter sich ausmachen.
Der ist hier allerdings für das Verständnis essenziell.
Rolf M. schrieb:> Der ist hier allerdings für das Verständnis essenziell.
Um zu verstehen, was genau der Fehler macht. In beiden Fällen ist der
Fehler fatal und die Wirkung gleich: Ein unbeteiligter Speicherbereich
wird verwendet und führt zu undefiniertem Verhalten.
Ich habe natürlich auch überlegt, ob ich dabei schreiben sollte, wo er
jetzt hingreift. Es hilft dem TO aber nicht beim Verständnis. Und die
Diskussion, wann ein Array zu einem einzelnen Ptr zerfällt, ist hier
sicher nicht dem TO angemessen. Anscheinend ja nichtmal den meisten
Diskutanten.
A. S. schrieb:> Und die> Diskussion, wann ein Array zu einem einzelnen Ptr zerfällt, ist hier> sicher nicht dem TO angemessen. Anscheinend ja nichtmal den meisten> Diskutanten.
Dieses schrecklich komplizierte Konzept, das im Standard 3 ganze Zeilen
belegt.
mh schrieb:> Dieses schrecklich komplizierte Konzept, das im Standard 3 ganze Zeilen> belegt.
Egal. Schau Dir den Thread hier an, wer da alles Probleme hat.
Oder schau Dir an, wie oft Du im Code sowas "int a[100]; ... foo(&a);"
findest, also dass der Adressoperator auf ein Array gesetzt wird.
Wenn Du eine gute Erklärung hast, verlinke sie gerne. Aber hier ist es
für den TO und andere mit ähnlicher Lernkurve schwer, noch was
rauszuziehen.
A. S. schrieb:> Wenn Du eine gute Erklärung hast, verlinke sie gerne. Aber hier ist es> für den TO und andere mit ähnlicher Lernkurve schwer, noch was> rauszuziehen.
Harte Realiät: Der TO ist idR nach einiger Zeit meist nur noch ein
Beispiel.
Die Info könnte doch für irgendwen nützlich sein.
A. S. schrieb:> mh schrieb:>> Dieses schrecklich komplizierte Konzept, das im Standard 3 ganze Zeilen>> belegt.>> Egal. Schau Dir den Thread hier an, wer da alles Probleme hat.>> Oder schau Dir an, wie oft Du im Code sowas "int a[100]; ... foo(&a);"> findest, also dass der Adressoperator auf ein Array gesetzt wird.
Bist du sicher, dass du damit keine Probleme hast? Oder was ist deiner
Meinung nach das Problem in deinem Beispiel?
> Wenn Du eine gute Erklärung hast, verlinke sie gerne. Aber hier ist es> für den TO und andere mit ähnlicher Lernkurve schwer, noch was> rauszuziehen.
Der Standard, oder wenn man dazu nicht in der Lage ist, reicht
https://en.cppreference.com/w/c/language/conversion. Das was auf der
Seite steht, sollte man als C Entwickler kennen.
mh schrieb:> Der Standard, oder wenn man dazu nicht in der Lage ist, reicht> https://en.cppreference.com/w/c/language/conversion. Das was auf der> Seite steht, sollte man als C Entwickler kennen.
Der Link ist jetzt Dein konstruktiver Beitrag hier im Thread? Und da
soll der TO oder jemand anders erkennen, was bei
A. S. schrieb:> int a[100]; ... foo(&a);"
falsch ist? Jedenfalls erwarte ich da foo(a) oder foo(&a[0]) oder von
mir aus auch foo(a+0). Oder irgendwas anderes, was foo erwartet. Nur
"&a" gibt (wenn foo eine Funktion ist) in keinem Fall Sinn.
Ja, Compiler akzeptieren das, doch trägt es zu der Verwirrung bei, der
der TO in seinem Code erlegen war.
A. S. schrieb:> Jedenfalls erwarte ich da foo(a) oder foo(&a[0]) oder von> mir aus auch foo(a+0). Oder irgendwas anderes, was foo erwartet. Nur> "&a" gibt (wenn foo eine Funktion ist) in keinem Fall Sinn.
foo(a), foo(&a[0]) und foo(a+0) sind offensichtlich falsch! Mein foo ist
übrigens void foo(int (*a)[100]).