Forum: PC-Programmierung Datenarray erst ab höherer Adresse übergeben


von Datenarray (Gast)


Lesenswert?

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?

: Verschoben durch Moderator
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Datenarray (Gast)


Lesenswert?

Danke!

von Bernd K. (prof7bit)


Lesenswert?

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.

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


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?
1
char bla[] = "Hallo";
2
3
puts(&bla[0]);

von Klaus (Gast)


Lesenswert?

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

von C# Beginner (Gast)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

C# Beginner schrieb:
> Damit vermeidet man die C-Pointer-Hacks

Das sind aber keine Hacks, sondern ganz normales C.

von C# Beginner (Gast)


Lesenswert?

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

von Dirk B. (dirkb2)


Lesenswert?

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.

von C# Beginner (Gast)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

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)

von C# Beginner (Gast)


Lesenswert?

> “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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von C# Beginner (Gast)


Lesenswert?

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

von Dirk B. (dirkb2)


Lesenswert?

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.

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.