2D Array an Funktion übergeben?!

Gast #5323752
Lesenswert?

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
Lesenswert?

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
Lesenswert?

> 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?
#5323797
Lesenswert?

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 #5324057
Lesenswert?

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!
#5324076
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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.
#5324380
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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 #5324728
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren