Forum: Mikrocontroller und Digitale Elektronik Daten aus uint32_t Array als int auslesen


von Florian S. (sirius7)


Lesenswert?

Hallo,

habe folgendes Array uint32_t data[]={1,2,3,4}

kann ich mit for-Schleife Daten direkt als int auslesen?

for (int * ptr = data; *ptr<=4, ++ptr)
{
   xQueueSend(theQ,ptr, portMAX_Delay);
}

würde mich über Eure Hilfe freuen, da ich leider selbst nicht testen 
kann.

Danke!

: Bearbeitet durch User
von DokuLeseVerweigerer (Gast)


Lesenswert?

Schwer zu sagen.....
Nicht immer ist int auch 32 Bit breit.
Das Verhalten ist Plattform abhängig.
Und nicht immer das gewünschte.

Was wünschst du dir denn?

von Florian S. (sirius7)


Lesenswert?

also es geht darum Fehler im Code zu finden. Theoretisch, selbst wenn 
int nicht 32 bit breit wäre, würden die unteren Bits, die dezimale 
Zahler beinhalten doch rein passen. Allerdings bin ich mir nicht sicher 
ob solche Zuweisung an sich überhaupt richtig ist.

von Sascha (Gast)


Lesenswert?

Also "kleiner gleich 4" führt imho dazu dass der auf data[4] zugreifen 
will und das gibts nicht weil data von 0-3 geht.

Das mit der int-Größe ist ein berechtigter Einwand, da muss man dann mal 
den C-Standard fragen wie groß int sein sollte.

Den sizeof-Operator gibts auch, wenn man zur Laufzeit prüfen muss ob 
Datentypen ineinanderpassen.

Achso und die Pointer-Arithmetik ist nur für ein 32-bit System richtig 
wenn ich mich nicht irre.
Du zählst ja von der Startadresse des Arrays hoch. Wenn das ein 8-bit 
System ist, ergibt ptr++ einfach das nächste Byte, aber nicht die 
nächste 32 bit Zahl. Denn die ist ja 4 byte weiter hinten.

Mit Array-Indizes zu arbeiten ist da etwas sicherer als Pointer.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Alex S. schrieb:
> Allerdings bin ich mir nicht sicher ob solche Zuweisung an sich
> überhaupt richtig ist.
WAS willst du denn erreichen? WIE du es erreichen willst, ist erst mal 
uninteressant...

> also es geht darum Fehler im Code zu finden.
Dann lass doch mal den Code sehen, sag, was er machen soll und was er 
stattdessen macht. Und wie du das feststellst...

von Florian S. (sirius7)


Angehängte Dateien:

Lesenswert?

es geht um dieses eine Task im Programm

von Florian S. (sirius7)


Lesenswert?

Hallo Sascha, ja ich denke auch so

von Markus F. (mfro)


Lesenswert?

Sascha schrieb:
> Achso und die Pointer-Arithmetik ist nur für ein 32-bit System richtig
> wenn ich mich nicht irre.

Du irrst dich.

von Mark B. (markbrandis)


Lesenswert?

Alex S. schrieb:
> habe folgendes Array uint32_t data[]={1,2,3,4}
>
> kann ich mit for-Schleife Daten direkt als int auslesen?
>
> for (int * ptr = data; *ptr<=4, ++ptr)
> {
>    xQueueSend(theQ,ptr, portMAX_Delay);
> }

So schon mal nicht, weil sich dieser Code gar nicht übersetzen lässt.

>
> würde mich über Eure Hilfe freuen, da ich leider selbst nicht testen
> kann.

Das Argument ist recht unsinnig. Jeder kann sich einen Compiler 
installieren. Und selbst wenn diese Möglichkeit ausfallen sollte, gibt 
es immer noch sowas wie:

http://codepad.org/
https://ideone.com/

von Florian S. (sirius7)


Lesenswert?

> es immer noch sowas wie:
>
> http://codepad.org/
> https://ideone.com/

wow das ist ja der Hammer! wenn die Dinge noch FreeRTOS können, bin ich 
grad glücklichster Mann der Welt )

von Sascha (Gast)


Lesenswert?

Markus F. schrieb:
>

Und würdest du vielleicht auch erklären warum?

Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher 
8 Bit weitergewandert, nicht 32.
Wenn ich data[i] nehme und dort i++ mache, dann bin ich 32 bit 
weitergewandert.

von Rolf M. (rmagnus)


Lesenswert?

Sascha schrieb:
> Markus F. schrieb:
>>
>
> Und würdest du vielleicht auch erklären warum?

Das ist leicht erklärt. Weil diese Aussage Blödsinn ist:

> Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher
> 8 Bit weitergewandert, nicht 32.

von Martin L. (martin_la)


Lesenswert?

In meinen Augen ist das was du tust nicht völlig falsch. Du hast nur 
eine Kleinigkeit vergessen.
Dein Schleifenkopf müsste aber folgendermaßen aussehen:
1
for(int* ptr=&data; ptr<(&data+4); ++ptr)

Du schreibst in ptr ja eine Adresse. Also z.B. 0x473e73a2 und wenn du 
das auf den Wert 4 prüfst, läuft deine Schleife ein paar mal zu oft ;)

Allerdings müssen darüf dann int und uint32_t gleich groß sein! Da 
solltest du dir natürlich sicher sein.

Hoffe ich konnte helfen.

von Mark B. (markbrandis)


Lesenswert?

Sascha schrieb:
> Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher
> 8 Bit weitergewandert, nicht 32.

Nein, da Datenbus und Adressbus nicht die gleiche Breite haben (müssen).

von Mark B. (markbrandis)


Lesenswert?

Martin L. schrieb:
> In meinen Augen ist das was du tust nicht völlig falsch. Du hast nur
> eine Kleinigkeit vergessen.
> Dein Schleifenkopf müsste aber folgendermaßen aussehen:
>
1
for(int* ptr=&data; ptr<(&data+4); ++ptr)

Bevor man aber sowas schreibt, lässt man den Käse mit dem Pointer sein 
und verwendet einfach das Array so wie es gedacht ist:
1
for (i=0; i<4; i++)
2
{
3
    // tu was mit data[i]
4
}

von Martin L. (martin_la)


Lesenswert?

Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher
8 Bit weitergewandert, nicht 32.


Hmmm das hab ich gerade nicht bedacht...

von DokuLeseVerweigerer (Gast)


Lesenswert?

Martin L. schrieb:
> Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher
> 8 Bit weitergewandert, nicht 32.

Der Datentype ist int * !
Und int kann 16/32/64 Bit breit sein, aber nicht 8.
Zumindest ist mir das noch nicht unter gekommen.

von Markus F. (mfro)


Lesenswert?

Sascha schrieb:
> Markus F. schrieb:
>>
>
> Und würdest du vielleicht auch erklären warum?
>
> Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher
> 8 Bit weitergewandert, nicht 32.
> Wenn ich data[i] nehme und dort i++ mache, dann bin ich 32 bit
> weitergewandert.

Natürlich.

Würden wir Assembler programmieren, hättest Du recht.

Tun wir (hier) aber nicht.

Ein uint32_t (aus stdint.h) ist immer 32 Bit breit. Auf jeder 
Plattform.
In C geschieht Zeigerarithmetik immer auf Basis der Grösse des 
Datentyps, auf den der Zeiger zeigt.
1
ptr++
Bedeutet also immer, dass die Adresse, die sich hinter dem Pointer 
versteckt um die Größe des Datentyps erhöht wird, auf die er zeigt.
Wenn ptr also z.B. 0x100 ist, ist er anschliessend 0x104. Auf jeder 
Plattform.

Das hier:
1
for (int * ptr = data; *ptr<=4, ++ptr)
2
{
3
   xQueueSend(theQ,ptr, portMAX_Delay);
4
}

tut übrigens auch was völlig anderes, als (wahrscheinlich) beabsichtigt.
*ptr <= 4 ist für alle Arrayelemente wahr. Wenn nicht rein zufällig im 
(nicht existenten) data[4] (bzw. den ebenso nicht existierenden 
Elementen dahinter) eine Zahl > 4 steht, schickt die Schleife munter 
allerhand Müll in die Queue...

von Axel S. (a-za-z0-9)


Lesenswert?

Alex S. schrieb:

> habe folgendes Array uint32_t data[]={1,2,3,4}
> kann ich mit for-Schleife Daten direkt als int auslesen?

Im Allgemeinen nicht. Im Speziellen wird es halbwegs funktionieren, wenn 
sizeof(int) == sizeof(uint32_t) ist. Denn nur in diesem Fall ist das 
Inkrementieren des Pointers äquivalent zum Zugriff auf das nächste 
Element des Arrays. Aber auch dann geht es in die Hose, wenn ein Eintrag 
des Arrays signed anders interpretiert wird als unsigned.

> for (int * ptr = data; *ptr<=4, ++ptr)
> {
>    xQueueSend(theQ,ptr, portMAX_Delay);
> }

Am gezeigten Code ist praktisch alles falsch.

1. der Funktionsparameter x wird gar nicht verwendet, sondern statt 
dessen das globale Array data benutzt

2. der Pointer ist von einem anderen Typ als das Array. s.o.

3. die Endeerkennung ist kaputt; sie liest immer mindestens eine 
Position über das Ende des Arrays hinaus und verläßt sich darauf, daß 
dort ein Wert > 4 im Speicher steht. Das kann beliebig in die Hose 
gehen.

von Rolf M. (rmagnus)


Lesenswert?

Mark B. schrieb:
> Martin L. schrieb:
>> In meinen Augen ist das was du tust nicht völlig falsch. Du hast nur
>> eine Kleinigkeit vergessen.
>> Dein Schleifenkopf müsste aber folgendermaßen aussehen:
>>for(int* ptr=&data; ptr<(&data+4); ++ptr)
> Bevor man aber sowas schreibt, lässt man den Käse mit dem Pointer sein

Zumindest, wenn man es so falsch schreibt, wie oben.

Ich würde nochmal ein paar Schritte zurückgehen und fragen, warum da 
überhaupt ein Array aus uint32_t ist, wenn dann nacher ein int* darauf 
an eine Funktion weitergegeben werden kann. Hier wird einfach das 
Pointerziel als anderer Datentyp uminterpretiert, mit allen 
Konsequenzen. Wenn int z.B. auf der Zielplattform nur 16 Bit breit ist, 
wird nur auf die Hälfte des Wertes zugegriffen. Welche Hälfte, hängt 
wiederum davon ab, ob die Plattform big oder little endian ist. Die 
for-Schleife darf auch nicht mit einem int* arbeiten, wenn das Array 
eigentlich von einem anderen Typ ist.

Solange int 32 Bit breit ist und man keine Zahlen größer als INT_MAX 
übergibt, und wenn man die Abbruchbedingung der Schleife repariert, 
funktioniert's trotzdem, ist aber immer noch murks.

von Bernd K. (prof7bit)


Lesenswert?

Sascha schrieb:
> Wenn ich ein 8-bit System habe und ptr++ mache, dann bin ich im Speicher
> 8 Bit weitergewandert, nicht 32.

Nein, Du hast ptr als int* deklariert, also bist Du mit ptr++ um die 
Größe eines int weitergewandert. Bei ABI von Atmel-AVR wären das zum 
Beispiel zwei Byte. In 20 Jahren sind es vielleicht 16 Byte, da steckt 
man nicht drin.

Deshalb nimmt man immer dann wenn auch nur der leiseste Anflug von 
Zweifel aufkommt oder plötzlich so wie hier aus heiterem Himmel die 
Frage auftaucht: "Ja wieviel Bytes sind das denn jetzt genau, ich will 
eigentlich exakt genau 4 Byte weil ich einem externen Zwang unterlegen 
bin, weil die Daten so strukturiert sind, das Protokoll, whatever" dann 
nimmt man die Posix-Typen mit expliziter Breitenangabe, also uint32_t 
und Konsorten und nicht das wankelmütige Wechselbalg von int.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

DokuLeseVerweigerer schrieb:
> Und int kann 16/32/64 Bit breit sein, aber nicht 8.
> Zumindest ist mir das noch nicht unter gekommen.

Ist gemäss C Standard auch nicht zulässig.

von (prx) A. K. (prx)


Lesenswert?

Axel S. schrieb:
> Am gezeigten Code ist praktisch alles falsch.

Schreib lieber, was in dieser Hausaufgabe richtig ist. ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Was ist denn, wenn der erste Wert im Array 0x40001 ist?

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.