Datenarray erst ab höherer Adresse übergeben

Gast #4954169
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?
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.
Moderator
Ob

1
  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.
Gast
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
Gast
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
Gast
Ich würde die Funktion
1
bool LeseDaten(uint8_t *data, uint32_t menge)
erweitern mit
1
bool LeseDaten(uint8_t *data, int16_t offset, uint32_t menge)
wo ich die Offset-Adresse (obiges Beispiel 10) angeben kann.
Damit vermeidet man die C-Pointer-Hacks
Moderator
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:

1
void BearbeiteWert(uint8_t *pwert);
2
void BearbeiteArray(uint8_t *array);
3

4
uint8_t wert, array[10];
5

6
BearbeiteWert(&wert);       // bearbeite gewöhnliche Variable
7
BearbeiteWert(&array[5]);   // bearbeite Array-Element mit Index 5
8
BearbeiteWert(&array[0]);   // bearbeite Array-Element mit Index 0
9

10
BearbeiteArray(array);      // bearbeite komplettes Array
11
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.
Gast
> 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:
1
bool LeseDaten(uint8_t *data, int16_t offset, uint32_t menge)
2
{ data +=offset;
evtl vorher noch mit Bereichskontrolle.

Der richtige Datentyp für offset und menge wären aber auch size_t, dann 
kann kein negativer Offset auftreten.
Gast
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.
Gast
> “Array subscript is not an integer” in C programme,


char mag er aber auch nicht, obwohl es ein integer-Datentyp ist!
1
char i1=0;
2
unsigned char i2=0;
3
int a[10];
4

5
printf("%d,%d\n", a[i1], a[i2]);


1
test.c: In function 'main':
2
test.c:12:20: warning: array subscript has type 'char' [-Wchar-subscripts]
3
 printf("%d,%d\n", a[i1], a[i2]);
4
                    ^

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.
Moderator
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.
Gast
> 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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.