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
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?
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.
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.
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...
Sascha schrieb: > Achso und die Pointer-Arithmetik ist nur für ein 32-bit System richtig > wenn ich mich nicht irre. Du irrst dich.
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/
> 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 )
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.
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.
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.
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).
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 | }
|
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...
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.
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...
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.
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.
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
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.
Axel S. schrieb: > Am gezeigten Code ist praktisch alles falsch. Schreib lieber, was in dieser Hausaufgabe richtig ist. ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.