Guten Morgen,
wieso kann man innerhalb der Funktion den Wert der zuvor rein
geschrieben wurde, korrekt auslesen und sobald sie verlassen wird und
die gleiche Speicherstelle wieder ausgelesen wird, steht irgendein Müll
drin?
> void readRAM( uint8_t *image )> {> image[156] = '1';> printf("%c",image[156]);> }> int main()> readRAM( (uint8_t *)ram );> printf("%c", ram[1][28]);
Du schreibst in der Funktion an Image[156] und liest in der main()
ram[1][28] aus?
Elisa W. schrieb:> Das man es irgendwie so auslesen kann?
Also 1.: Du liest es ja gar nicht aus sondern beschreibst es.
Und 2.: Was willst du denn genau machen? Das ist wohl sinnvoller zu
klären als jetzt noch 15 Posts um den heißen Brei zu reden.
Ich möchte ein Array senden über einen BUS was 64x128 Bytes groß ist, Da
würde sich diese Art wie Ich zu letzt gepostet habe sehr anbieten. Das
ist ziemlich übersichtlich.
M. K. schrieb:> void sendRAM( uint8_t image[] )> {> for(uint8_t x = 0 ; x < 64 ; x++)> {> for(uint8_t i = 0; i < 128 ; i++)> {> send(image[x+64*i]);> }> }> }
Jetzt muss Ich aber noch mal was Fragen. Wieso x+64? Wenn Ich von 0
Anfangen will zu lesen?
Elisa W. schrieb:> Jetzt muss Ich aber noch mal was Fragen. Wieso x+64? Wenn Ich von 0> Anfangen will zu lesen?
Beginnt doch mit 0. Zu Beginn ist doch x und i jeweils 0, damit greift
man auf image[0] zu. Das letzte Element ist image[63+64*127] zu, das ist
image[8191], also das letzte Element von image[]
Elisa W. schrieb:> Jetzt muss Ich aber noch mal was Fragen. Wieso x+64? Wenn Ich von 0> Anfangen will zu lesen?
Mathe 2 Klasse : Punkt vor Strichrechnung!
ich würde die Größeninformation nicht irgendwo in der Funktion
verstecken sondern entweder
void sendRAM( uint8_t image[64][128] )
oder sendRAM( uint8_t *image, int xsize, int ysize)
verwenden
Ralf schrieb:> Elisa W. schrieb:>> Jetzt muss Ich aber noch mal was Fragen. Wieso x+64? Wenn Ich von 0>> Anfangen will zu lesen?>> Mathe 2 Klasse : Punkt vor Strichrechnung!
Mal nicht so überheblich!
2.Klasse - Rechnen hat mit Priorität und Assoziativität von Operatoren
in C erst mal gar nichts zu tun!
Auch dann nicht - wenn es zufällig Parallelen gibt!
Danke!
Walter K. schrieb:> in C erst mal gar nichts zu tun!> Auch dann nicht - wenn es zufällig Parallelen gibt!
Ganz rein zufällig macht das der C-Compiler genau deswegen so weil es
die Mathematik so lehrt. Das ist keine Erfindung der Programmierer des
Compilers.
Walter K. schrieb:>> Mathe 2 Klasse : Punkt vor Strichrechnung!>> Mal nicht so überheblich!>> 2.Klasse - Rechnen hat mit Priorität und Assoziativität von Operatoren> in C erst mal gar nichts zu tun!
Auch in C gilt selbstverständlich Punkt vor Strich. Dass das als Teil
einer größeren Liste von Operator-Prioritäten und Assoziativitäten
umgesetzt ist, ändert daran nichts.
> Auch dann nicht - wenn es zufällig Parallelen gibt!
Die gibt es nicht zufällig, sondern in voller Absicht, da es ziemlich
blöd wäre, solche grundlegenden Regeln nicht zu übernehmen.
> Danke!
Gern geschehen!
Walter schrieb:> ich würde die Größeninformation nicht irgendwo in der Funktion> verstecken sondern entweder>> void sendRAM( uint8_t image[64][128] )
Das bringt nicht viel. Der Parameter ist ein Zeiger auf ein Array aus
128 Elementen vom Typ uint8_t. Die 64 wird vom Compiler weder beim
Aufruf berücksichtigt, noch kann man sie innerhalb der Funktion wieder
irgendwie zurückgewinnen (sizeof gibt dir nur die Größe eines Zeigers).
Am Ende ist es also nur eine Art Doku für denjenigen, der diesen
Funktionskopf liest.
Ein 2D-Array zerfällt bei einem Funktionsaufruf nicht in einen
Doppelzeiger.
Seit C99 gibt es VLA (Variable Length Array).
Die haben zwar einen schlechten Ruf (wenn man damit Arrays definiert).
Als Funktionsparameter oder auch als Zeiger auf ein Array sind sie
super.
Walter schrieb:> ich würde die Größeninformation nicht irgendwo in der Funktion> verstecken sondern entweder>> void sendRAM( uint8_t image[64][128] )>> oder sendRAM( uint8_t *image, int xsize, int ysize)>> verwenden
ich halte die 2. Variante für die sauberste Lösung
Rolf M. schrieb:> Die gibt es nicht zufällig, sondern in voller Absicht, da es ziemlich> blöd wäre, solche grundlegenden Regeln nicht zu übernehmen.
Deshalb kennt der Taschenrechner/Calculator des in diesem Forum so hoch
geschätzten und verehrten Betriebssystem-Schrotts - namens MS-Windows
die Punkt vor Strich-Regel nur im "Wissenschaftlichen Mode" ;-)
Dirk B. schrieb:> Ein 2D-Array zerfällt bei einem Funktionsaufruf nicht in einen> Doppelzeiger.
Nein, es zerfällt wie ich oben schrieb in einen Zeiger auf ein Array.
> Als Funktionsparameter oder auch als Zeiger auf ein Array sind sie> super.> sendRAM(int xsize, int ysize, uint8_t image[xsize][ysize])> Die Reihenfolge ist wichtig, erst die Dimensionen, dann die Adresse.> In der Funktion kann man dann Problemlos mit [] auf das Array zugreifen.
Auch das ändert aber nichts daran, dass es ein Zeiger auf ein Array ist
und das xsize beim Parameter image keine Auswirkung hat. Wenn man den
Parameter stattdesen als uint8_t image[][ysize] angibt, hat das exakt
die gleiche Bedeutung.
Das kann Ich jetzt noch nicht wirklich nachvollziehen.
Ich habe ein Array mit einem Reservierten Speicherbereich von 64 * 128
Bytes.
Diese sind alle hintereinander angeordnet, richtig?
Das heißt ich müsste von
Elisa W. schrieb:> Das kann Ich jetzt noch nicht wirklich nachvollziehen.> Ich habe ein Array mit einem Reservierten Speicherbereich von 64 * 128> Bytes.>> Diese sind alle hintereinander angeordnet, richtig?> Das heißt ich müsste von>
1
>Image[0]-Image[127]
2
>
> lesen um Bildlich gesehen auf>
1
>RAM[1][0]
2
>
> zu kommen oder nicht?
Öhm, nö. Schau dir auf jeden Fall noch mal die Zeigersachen an. Ein
Array ist ja eigentlich auch nix anderes als ein Zeiger.
M. K. schrieb:> Ein Array ist ja eigentlich auch nix anderes als ein Zeiger.
Arg! Bitte nicht sowas verbreiten. Das ist falsch! Ein großer Teil der
Probleme, die Leute mit Zeigern in C haben, resultiert daraus, dass sie
den Unterschied nicht verstehen - ganz besonders bei mehrdimensionalen
Arrays.
Rolf M. schrieb:> Arg! Bitte nicht sowas verbreiten. Das ist falsch!
Hm, aber das hier sieht so verdammt ähnlich aus:
1
uint8_t*myPointer;
2
myPointer[0]=myValue0;
3
myPointer[1]=myValue1;
4
myPointer[2]=myValue2;
5
6
uint8_tmyArray[3];
7
myArray[0]=myValue0;
8
myArray[1]=myValue1;
9
myArray[2]=myValue2;
Also ich käme nie auf die Idee ein Array als Pointer zu missbrauchen,
klar. Aber das Verhalten von Arrays und Pointern ist doch recht ähnlich.
Kannst du das etwas genauer erläutern?
Elisa W. schrieb:> Ich habe ein Array mit einem Reservierten Speicherbereich von 64 * 128> Bytes.>> Diese sind alle hintereinander angeordnet, richtig?> Das heißt ich müsste vonImage[0] - Image[127]> lesen um Bildlich gesehen aufRAM[1][0]> zu kommen oder nicht?
ja, Dein Array liegt sequentiell im Speicher.
D.h. mehrdimensionale Arrays in C sind letztendlich immer
eindimensional.
wie Du richtig geschrieben hast:
( array_intern ist jetzt nur ein Konstrukt zur Erklärung )
array[0][000] => array_intern[0]
array[0][001] => array_intern[1]
array[0][002] => array_intern[2]
...
array[0][127] => array_intern[127]
array[1][000] => array_intern[128]
array[1][001] => array_intern[129]
array[1][002] => array_intern[130]
...
array[1][127] => array_intern[255]
......
array[63][127] => array_intern[8191]
Und nein - ein Array ist kein Zeiger .. aber es besteht im Prinzip nur
aus Zeigern, welche auf die zum Array gehörenden Variablen zeigen.
M. K. schrieb:> Hm, aber das hier sieht so verdammt ähnlich aus:>> uint8_t* myPointer;> myPointer[0] = myValue0;
Wo zeigt denn myPointer hin?
Wie sieht es mit sizeof aus?
Kannst du das Array auf einen andere Speicheradresse zeigen lasse?
Kannst du die Größe von dem Array ändern?
Ähnlich ist nicht gleich.
Bei beiden funktioniert Zeigerarithmetik und die dereferenzierung
mittels * und [].
Dann stelle Ich mir das wie eine Art Tabelle vor.
ram[Zeile 0][Spalte 0] = 'a'
ram[Zeile 1][Spalte 0] = 'b'
Oben in der Ausgabe ist das 'b' nicht an Zeile '1'. Wieso?
Elisa W. schrieb:> Oben in der Ausgabe ist das 'b' nicht an Zeile '1'. Wieso?
Weil du ja quasi x und y einfach nur zusammenaddierst.
Elisa W. schrieb:> for( ; y < 64 ; y++)> {> printf("Zeile %d.: ",y);> for( x = 0 ; x < 128 ; x++)
Bei jedem Schleifendurchlauf der inneren Schleife gehst du um genau ein
Element uint8_t, also ein Byte weiter.
> {> printf("%c",image[x]);> }> printf(" END \r\n");> image++;
Bei jedem Schleifendurchlauf der äußeren Schleife gehst du ebenfalls um
genau ein Element uint8_t, also ein Byte weiter.
> }
Okay.
Für eine Anfängerin wie Mich ist das ziemlich tricky.
Schade das man nicht einfach wie an anderer Stelle mit [x][y] drauf
zugreifen kann. Das würde viel zum Verständniss beitragen.
Nimm mal ein kleineres Array und lass dein Prog Schritt für Schritt mit
einem Debugger laufen und schau zu was passiert. Ansonsten sie dir die
Wikibook links an.
M. K. schrieb:> Deswegen schrieb ich "eigentlich ein Zeiger" ;)
Genauso wie das Gleichsetzen von Zeigern und Arrays "eigentlich" ein
Bein ist. Denn dieser Vergleich hinkt sehr stark.
Rolf M. schrieb:>> void sendRAM( uint8_t image[64][128] )>> Das bringt nicht viel.
mir schon, zumindest kann ich dann mit
image[y][x]
auf das array zugreifen und muss nicht so einen hack schreiben
image[x+64*i]
und das ganze dann vielleicht noch an 10 Stellen in der Funktion
Elisa W. schrieb:> uint8_t y = 0, x = 0;>> for( ; y < 64 ; y++)
Initialisier die Variablen direkt in der For Schleife, nicht zuvor. Der
Compiler optimiert das schon weg, nur bewahrt es den Code hinsichtlich
der Fehleranfälligkeit und der Compiler kann zudem besser optimieren.
So machst du deinen Code nur unübersichtlicher durch eine vermeintliche
Optimierung und gewinnst rein gar nichts.
Walter schrieb:> Rolf M. schrieb:>>> void sendRAM( uint8_t image[64][128] )>>>> Das bringt nicht viel.>> mir schon, zumindest kann ich dann mit> image[y][x]>> auf das array zugreifen
Ja, das schon. Ich meinte, dass die 64, die dort steht, keine Auswirkung
hat und nur Augenwischerei ist. Du schriebst, dass du die 64 nicht in
der Funktion "verstecken" willst. Weiter als bis zum Funktionskopf
schafft sie es so aber auch nicht.
> und muss nicht so einen hack schreiben> image[x+64*i]>> und das ganze dann vielleicht noch an 10 Stellen in der Funktion
Wenn du das an 10 Stellen in der Funktion brauchst, kannst du den Index
auch einmal am Anfang berechnen und dann an den 10 Stellen nur noch
benutzen.
Rolf M. schrieb:> Wenn du das an 10 Stellen in der Funktion brauchst, kannst du den Index> auch einmal am Anfang berechnen und dann an den 10 Stellen nur noch> benutzen.
*64 ist nur ein Shift, daher relativ billig, zudem optimiert der
Compiler das eh raus sofern aktuell genug ist.
Rolf M. schrieb:> Genauso wie das Gleichsetzen von Zeigern und Arrays "eigentlich" ein> Bein ist. Denn dieser Vergleich hinkt sehr stark.
Nochmal die Bitte: Erkläre es mir/uns (hier lesen sicher mehr mit) bitte
einmal. Das wäre sehr nett.
M. K. schrieb:> Nochmal die Bitte: Erkläre es mir/uns (hier lesen sicher mehr mit) bitte> einmal. Das wäre sehr nett.
Moin,
ich verstehe zwar nicht so recht, was es da nicht zu verstehen gibt,
aber ich versuche es mal:
Ein Pointer ist eine Variable. Dier wird angelegt und vom Linker
locatiert. Sie belegt exakt sviel speicher, wie eine Adresse auf deinem
Target benötigt (mein Cortex M7 4Byte), mehr nicht.
Ein Array besteht aus dem Speicherplatz der Daten die das Array bilden.
ZB ein paar tauesend bytes (je nach groesse).
Der Linker muss diese Daten auch irgendwo hinlegen. Und somit gibt es
eine Adresse bei der die Daten liegen. Aber es gibt keinen Pointer.
Man kann zB eine Pointer anlegen, die Adresse des Pointers ermitteln
(&myptr), an eine Funktion uebergeben, die ein Datenobjekt kreiert
(dafuer speicher allociert der irgendwo wo platz ist zum liegen kommt)
und diese Adresse in den Pointer schreibt.
Danach kann der Aufrufer seinen Pointer dereferenziern und somit auf das
Datenobject zugreifen. Er kann aber auch seine Pointer ins Nirvana
zeigen
lassen und dort dereferenzieren.
Da kommt nur meistens nix gescheites bei raus.
Darth Moan schrieb:> Ein Pointer ist eine Variable. Dier wird angelegt und vom Linker> locatiert. Sie belegt exakt sviel speicher, wie eine Adresse auf deinem> Target benötigt (mein Cortex M7 4Byte), mehr nicht.>> Ein Array besteht aus dem Speicherplatz der Daten die das Array bilden.> ZB ein paar tauesend bytes (je nach groesse).> Der Linker muss diese Daten auch irgendwo hinlegen. Und somit gibt es> eine Adresse bei der die Daten liegen. Aber es gibt keinen Pointer.
Da fragt ein Anfänger nach den Eigenheiten von zweidimensionalen Feldern
in C -
und dann kommt zum Schluss so ein Stuss, wie der von Darth Moin -
und bleibt dann als letzter Beitrag unwidersprochen stehen!
Walter K. schrieb:> Da fragt ein Anfänger nach den Eigenheiten von zweidimensionalen Feldern> in C -> und dann kommt zum Schluss so ein Stuss, wie der von Darth Moin -> und bleibt dann als letzter Beitrag unwidersprochen stehen!
Tja, du willst jetzt also den Anfängern einreden, dass es keinen
Unterschied zwischen einem Pointer und einem Array gibt.
Wer soetwas behauptet, der ist entweder dumm, oder niedertraechtig weil
er Anfaengern Stuss einreden will.
Oder er hat gar nicht gelesen, worauf jemand geantwortet hat?
M. K. schrieb:> Array ist ja eigentlich auch nix anderes als ein Zeiger.M. K. schrieb:>> Genauso wie das Gleichsetzen von Zeigern und Arrays "eigentlich" ein>> Bein ist. Denn dieser Vergleich hinkt sehr stark.>> Nochmal die Bitte: Erkläre es mir/uns (hier lesen sicher mehr mit) bitte> einmal. Das wäre sehr nett.
Aber lesen ist ja auch so old school.
Rolf M. schrieb:>> und muss nicht so einen hack schreiben>> image[x+64*i]>>>> und das ganze dann vielleicht noch an 10 Stellen in der Funktion>> Wenn du das an 10 Stellen in der Funktion brauchst, kannst du den Index> auch einmal am Anfang berechnen und dann an den 10 Stellen nur noch> benutzen.
ja, wenn man immer nur auf ein Element des arrays zugreifen wollte, das
ist aber eher selten,
was ist einfacher zu lesen und zu verstehen:
value = image[x-1,y-1] + image[x, y-1] + image[x+1, y-1]
oder
value = image[(y-1)*64+x-1] + image[(y-1)*64+x] + image[(y-1)*64+x-1]
Ich finde ja, an deiner zweiten Variante sieht man viel schneller, dass
da wohl 64 Zeilen durchlaufen werden, an der erste Variante sieht man
das IMO nicht sofort.