2D Array an Funktion übergeben?!

Gast #5323752
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4

5
void readRAM( uint8_t **image )
6
{  
7
  *image[0] = '1';
8
  printf("%c",*image[0]);
9
}
10

11

12
int main()
13
{
14
  uint8_t ram[64][128];
15

16
  readRAM( (uint8_t **)ram );
17
  printf("%c", *ram[0]);
18
  
19
    return 0 ;
20
}
#5323764
mehr als nur ein Stern, so klappts:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4
void readRAM( uint8_t *image )
5
{
6
    image[156] = '1';
7
    printf("%c",image[156]);
8
}
9

10

11
int main()
12
{
13
    uint8_t ram[64][128];
14
    
15
    readRAM( (uint8_t *)ram );
16
    printf("%c", ram[1][28]);
17
    
18
    return 0 ;
19
}
Gast #5323773
> 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?
Gast #5323779
Kann man nicht irgendwie auf das Array anders drauf zugreifen?
1
void readRAM( uint8_t *image )
2
{
3
    *image[0][0] = '1';
4
}
Das man es irgendwie so auslesen kann?
Gast #5323785
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.
Gast #5323790
So ungefähr..
1
void sendRAM( uint8_t *image )
2
{
3
  uint8_t i = 0;
4
  
5
  for(uint8_t x = 0 ; x < 64 ; x++)
6
  {
7
    for( ; i < 128 ; i++)
8
    {
9
      send(image[x][i]);
10
    }
11
  }
12
}
#5323797
Dann mach das doch genau so

Zur besseren Lesbarkeit würde ich es aber so schreiben:
1
void sendRAM( uint8_t image[] )
2
{
3
  for(uint8_t x = 0 ; x < 64 ; x++)
4
  {
5
    for(uint8_t i = 0; i < 128 ; i++)
6
    {
7
      send(image[x+64*i]);
8
    }
9
  }
10
}
Ist meiner Meinung nach übersichtlicher
Gast #5323917
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?
#5323925
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[]
Gast #5324056
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
Gast #5324057
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!
Gast #5324073
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.
#5324076
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.
#5324092
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.
1
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.
Gast #5324093
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
Gast #5324110
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"  ;-)
#5324130
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.
Gast #5324163
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]
lesen um Bildlich gesehen auf
1
RAM[1][0]
zu kommen oder nicht?
#5324335
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.
#5324345
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.
#5324380
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_t myArray[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?
Gast #5324394
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.
#5324483
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 [].
Gast #5324551
Anbei mal ein Screenshot.

Wenn Ich..
1
  ram[0][0] = 'a';
2
  ram[1][0] = 'b';
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?
1
void readRAM(uint8_t *image)
2
{
3
  uint8_t y = 0, x = 0;
4
  
5
  for( ; y < 64 ; y++)
6
  {
7
    printf("Zeile %d.:      ",y);
8
    for( x = 0 ; x < 128 ; x++)
9
    {
10
      printf("%c",image[x]);
11
    }
12
    printf(" END \r\n");
13
    image++;
14
  }
15
}
16

17
int main ()
18
{
19
  uint8_t ram[64][128];
20
    
21
  memset((uint8_t*)ram,'0',8091);
22
  
23
  ram[0][0] = 'a';
24
  ram[1][0] = 'b';
25
  
26
  readRAM((uint8_t*)ram);
27

28
    return 0;
29
}
Angehängte Dateien:
#5324572
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.

>   }
Gast #5324581
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.
Gast #5324643
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.
Gast #5324728
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
Gast #5324784
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.
#5324930
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.
Gast #5325006
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.
Gast #5325148
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.
Gast #5326600
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!
Gast #5326865
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.
Gast #5326943
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]

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 8 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.