Hallo,
ich habe die Funktion vom Typ:
bool LeseDaten(uint8_t *data, uint32_t menge)
und Daten:
uint8_t MeineDaten[100] = {irgendwas};
Nun möchte ich gerne die Daten erst ab der Adresse 10 auslesen.
Wenn ich den Ansatz wähle:
LeseDaten(&MeineDaten+10, 20);
dann erhalten ich eine Warnung, incompatible Pointer Type.
Wie kann ich dieses Problem lösen?
Datenarray schrieb:> LeseDaten(&MeineDaten+10, 20);
Lass den Adressperator weg:
LeseDaten(MeineDaten + 10, 20);
Wenn Du den Adressoperator verwenden willst, musst Du
LeseDaten(&MeineDaten[10], 20);
verwenden, aber ob das übersichtlicher ist?
Rufus Τ. F. schrieb:> Datenarray schrieb:> LeseDaten(&MeineDaten+10, 20);>> Lass den Adressperator weg:>> LeseDaten(MeineDaten + 10, 20);>> Wenn Du den Adressoperator verwenden willst, musst Du>> LeseDaten(&MeineDaten[10], 20);>> verwenden, aber ob das übersichtlicher ist?
Es ist klarer. Das andere macht sich unlogischen syntaktischen Zucker
zunutze, darüber kann man geteilter Meinung sein.
Man sieht ja auch schön wie der TE intuitiv zielsicher in diese Falle
reingestolpert ist obwohl sein Gedankengang nachvollziehbar und logisch
konsistent war.
MeineDaten+10// Nimm die Startadresse des Arrays und hüpfe 10
2
// (Element-)Schritte weiter
oder
1
&MeineDaten[10]// Nimm Element Nr. 10 und bilde davon die Adresse
ist in meinen Augen fast gleichwertig (mit leichter Tendenz zur ersten
Variante) und damit Geschmackssache.
Bernd K. schrieb:> Es ist klarer. Das andere macht sich unlogischen syntaktischen Zucker> zunutze, darüber kann man geteilter Meinung sein.
Der syntaktische Zucker sind die eckigen Klammern, denn a[i] ist die
Kurzschreibweise für *(a+i). Der Verzicht auf syntaktischen Zucker würde
also für die erste Variante sprechen.
> Man sieht ja auch schön wie der TE intuitiv zielsicher in diese Falle> reingestolpert ist obwohl sein Gedankengang nachvollziehbar und logisch> konsistent war.
Die Methode mit der expliziten Zeigeraddition war für ihn offensichtlich
naheliegender. Er hat vielleicht gedacht: Warum soll ich den Umweg über
das Array-Element gehen (das in diesem Zusammenhang ja überhaupt nicht
interessiert), wenn es auch den direkten Weg gibt?
Dass der Array-Name hier als Zeiger auf das erste Element interpretiert
wird und deswegen der Adressoperator fehl am Platz ist, hat er jetzt ja
gelernt. Die Behandlung von Arrays ist in C nun einmal etwas speziell,
aber trotzdem sehr einfach im Vergleich zu ein paar anderen speziellen
C-Features.
Yalu X. schrieb:> Ob>> MeineDaten + 10 // Nimm die Startadresse des Arrays und hüpfe 10> // (Element-)Schritte weiter>> oder>> &MeineDaten[10] // Nimm Element Nr. 10 und bilde davon die Adresse>> ist in meinen Augen fast gleichwertig (mit leichter Tendenz zur ersten> Variante) und damit Geschmackssache.
Seh ich genau umgekehrt. Wenn ich Fall 1 so lese, ist MeineDaten erst
mal eine Variable die um 10 erhöht wird. Das das ein Array und damit
eigentlich ein Pointer ist, muß ich erstmal nachsehen.
Beim zweiten Fall sehe ich die eckigen Klammern, das sagt mir sofort es
ist ein Array.
MfG Klaus
Klaus schrieb:> Beim zweiten Fall sehe ich die eckigen Klammern, das sagt mir sofort es> ist ein Array.
Wenn aber auf das erste Element zugegriffen wird, fallen die eckigen
Klammern und der Adressoperator sowieso weg, oder schreibst Du ernsthaft
so etwas hier?
Rufus Τ. F. schrieb:> schreibst Du ernsthaft so etwas hier?
Sicher nicht. Aber puts() deutet mit string in seinem Namen schon mal
auf ein Array hin.
Wenn ich etwas leichter verständlich machen kann, tue ich das. Deswegen
schreibe ich auch immer "<< 8" statt "* 256" wenn ich etwas schieben
will und "|" wenn ich OR meine und nicht "+", selbst wenn ich weiß, das
das möglicherweise äquivalent ist.
MfG Klaus
Rufus Τ. F. schrieb:> puts(&bla[0]);
Die Schreibweise &a[i] verwende ich mitunter, um damit auszudrücken,
dass es um einen Pointer auf ein einzelnes Array-Element und nicht um
ein Teil-Array geht. Unter diesem Gesichtspunkt kann dann auch der etwas
seltsam anmutende Ausdruck &a[0] sinnhaftig sein.
Beispiel:
BearbeiteArray(array+5);// bearbeite Teil-Array ab Index 5
Aber wie schon oben geschrieben, halte ich das für Geschmackssache.
Deswegen störe ich mich nicht daran, wenn jemand eine andere
Schreibweise bevorzugt.
> Das sind aber keine Hacks, sondern ganz normales C.Jedes Hack lässt sich (in Normalform) compilieren und macht was es
soll.
Somit ist jedes Hack "ganz normales C".
Obiges Hack (Pointer-Arithmetik) würde bei manchen Architekturen (kein
linearer Speicher-Address-Raum, sondern segmentierter) eventuell nicht
mehr funktionieren.
C# Beginner schrieb:> Obiges Hack (Pointer-Arithmetik) würde bei manchen Architekturen (kein> linearer Speicher-Address-Raum, sondern segmentierter) eventuell nicht> mehr funktionieren.
Ob das aber mit dem C-Standard harmoniert?
Zudem wäre die erste Operation in der von dir vorgeschlagenen Funktion:
Oft bekomme ich warnings
“Array subscript is not an integer” in C programme,
somit mache ich die indices halt als integer, wenn der Compiler das so
will.
Negativ sollten die nach Möglichkeit nicht werden, da gebe ich Dir
Recht.
C# Beginner schrieb:> Oft bekomme ich warnings> “Array subscript is not an integer” in C programme,> somit mache ich die indices halt als integer, wenn der Compiler das so> will.
Er möchte einen integer-Typ (also einen Ganzzahltyp) haben. Zeiger
gehören nicht dazu. (long, char und size_t gehen z.B. auch)
Ok, es gibt keine genaue Definition von "hack".
Ob man Pointer-Arithmetik dazurechnet, soll jeder selber für sich
entscheiden.
Ich habe das auch schon gemacht.
Viele Coding-Standards (z.B. Misra) verbieten es.
C# Beginner schrieb:> Obiges Hack (Pointer-Arithmetik) würde bei manchen Architekturen (kein> linearer Speicher-Address-Raum, sondern segmentierter) eventuell nicht> mehr funktionieren.
Doch. Wenn &a[i] funktioniert, funktioniert auch a+i. Wie ich oben schon
schrieb, ist a[i] nur eine Kurzschreibweise von *(a+i).
Also ist
&a[i]
= &*(a+i) (& und * heben sich auf und können damit weggelassen werden)
= a+i
D.h. der Unterschied zwischen &a[i] und a+i ist rein syntaktischer
Natur, auch bei Prozessoren mit segmentiertem Adressraum.
C# Beginner schrieb:> char mag er aber auch nicht, obwohl es ein integer-Datentyp ist!
Das liegt daran, dass char je nach Compiler signed oder unsigned sein
kann, was bei der Array-Indizierung u.U. zu überraschenden Ergebnissen
führt. Wie du bereits festgestellt hast, lässt sich das Problem mit
unsigned char beheben, ebenso mit signed char. Da int immer signed ist,
wird dort nicht gewarnt.
> ist a[i] nur eine Kurzschreibweise von *(a+i).
Das war weniger der Knackpunkt,
sondern dass man mit "a+i" oder "&a[i]" (a = array, i = integer
Datentyp) ein neues Array macht und dieses einer Unterfunktion übergibt.
C# Beginner schrieb:> "a+i" oder "&a[i]"> (a = array, i = integer Datentyp)
Da (a+i) == (i+a) ist kann man auch &i[a] schreiben.
Demnach ist nur wichtig, das eine Adresse und ein Ganzahltyp daran
beteiligt sind.
C# Beginner schrieb:> ein neues Array macht
Da wird nichts neues erstellt und
Arrays erzeugt man nur durch deren Definition, nicht durch irgendwelche
Operationen
> und dieses einer Unterfunktion übergibt.
Dies erfolgt immer über die Adresse.