# Array anlegen



## HolgerX (12. Juli 2004)

Ich will ein zweidimensionales Array anlegen.
	
	
	



```
unsigned char image[spalten][zeilen];
```
Als Parameter bekomme ich 
	
	
	



```
... const int zeilen, const int spalten, ...
```
Dabei bekomme ich die Fehlermeldung: *Konstanter Ausdruck erwartet*
Hallo, spalten und zeilen sind doch konstant!
Ausserdem bekomme ich noch folgende Fehlermeldung:
*Reservierung eines Feldes der konstanten  Größe 0 nicht möglich
<unbekannt> Feldindex fehlt
'image' : unbekannt Größe*

Wo ist das Problem?


----------



## RedWing (12. Juli 2004)

```
1 bool initArray(const int a, const int b){
      2 
      3         unsigned char feld[a][b];
      4         return true;
      5 }
      6 
      7 int main(void){
      8 
      9         initArray(5,3);
     10 }
```

Das lässt sich vom gcc prima übersetzen...

Gruß

RedWing


----------



## Kachelator (13. Juli 2004)

@Redwing:  
Und was soll das nützen? Die Arraygrössen müssen konstant sein, darum geht es. Sind ja bei dir auch in gewisser Weise. Vermutlich frisst der Compiler es nur, weil das char-Array ohnehin wegoptimiert wird. Oder sehe ich da was falsch?
Letztenendes geht es ja darum, dass dem Compiler die Grösse des Arrays zur Compile-Zeit bekannt sein muss.

@HolgerX:
Wie gesagt: Wenn du ein Array auf dem Stack definierst, muss die Anzahl der Arrayeinträge eine Konstante sein. Du intialisierst die "konstanten Variablen" aber gar nicht bei der Deklaration. Wie soll das gehen? Nachher geht es ja nicht mehr. Oder sSind es tatsächlich Funktionsparameter?


----------



## squeaker (13. Juli 2004)

du musst das Array dynamisch mit malloc anfordern. Die benötigte Speichergröße dabei ist Zeilenzahl*Spaltenzahl*Speicher_für_typ.
Dann den Zeiger casten und das müsste reichen.


----------



## RedWing (13. Juli 2004)

@Kacheletor

1.)Wer sagt das die Feldgröße zur Compile Zeit bekannt sein muss?
Ein statischer Datentyp wird dadurch charkterisiert, das er zur Laufzeit in seiner 
Größe nicht veränderbar ist, oder?

2.) Sind meine größen nicht Konstant?

3.) Was heißt wegoptimieren?

Gruß

RedWing


----------



## squeaker (13. Juli 2004)

> _Original geschrieben von RedWing _
> *@Kacheletor
> 
> 1.)Wer sagt das die Feldgröße zur Compile Zeit bekannt sein muss?
> ...



Ein statischer Datentyp wird dadurch charakterisiert, dass er zur Laufzeit in seiner Größe nicht veränderbar ist, da die Größe zur Compile-Zeit festgelegt wurde. Der Speicher wird dabei in einem speziellen Codesegement reserviert (.DATA normalerweise) und nicht auf dem HEAP.

Deine Größen sind vielleicht konstant zur Laufzeit - können sich aber von Lauf zu Lauf ändern bzw. von Funktionsaufruf zu Funktionsaufruf.

Wegoptimiert heisst, dass der Code nicht in die exe geschrieben wurde, da der Compiler festgestellt hat, dass er nie ausgeführt wird. Dadurch entsteht dann natürlich auch kein Fehler zur Compilezeit. Am besten ist, du schaust die das Disassembly von deinem Programm in einem Debugger wie z.B. OllyDbg an und verfolgst den Programmablauf im Einzelschrittmodus. Dann müsstest du es sehen.


----------



## HolgerX (13. Juli 2004)

Also, meine Parameter sind Konstante,

Aber ich habe das jetzt mit *malloc* probiert. - Natürlich habe ich keine Ahnung, ob ich das so richtig gemacht habe.
	
	
	



```
// Das Bild als zweidimensionales Array
	unsigned char **image;
	image = (unsigned char **) malloc(spalten*zeilen *sizeof(unsigned char) );
```
Jetzt habe ich das Problem, wenn ich *image* Werte zuweisen will.
	
	
	



```
for(zeile = 0; zeile<zeilen; zeile++)
	{
		for(spalte = 0; spalte<spalten; spalte++)	
		{
			i = zeile * spalten + spalte;
			image[spalte][zeile] = input[i];						
		}

	}
```
Wobei folgende Parameter existieren:
	
	
	



```
void CSegmentation::EdgeTracing(unsigned char *input, const int zeilen, const int spalten, int minLength)
```
Dabei bricht das Programm immer mit Fehlermeldung ab, wenn ich die Zeile mit der Zuweisung von image erreiche.  
Wieso? - Kompilieren tut er ja ohne Probleme.


----------



## squeaker (13. Juli 2004)

Sind deine Parameter zur Compile-Zeit bekannt? oder erst zur Laufzeit?

Hier sind Codebeispiele:

http://www.pixelate.co.za/issues/12/articles/dynamicarrays/dynamicarrays.html


----------



## HolgerX (13. Juli 2004)

Zur Laufzeit!


----------



## squeaker (13. Juli 2004)

Siehe link oben - da ist ein Codebeispiel. Ich kann es leider hier nicht ausprobieren - bin auf Arbeit.

probier mal: image[ i ] stattdessen aus.


----------



## RedWing (13. Juli 2004)

@Holger:

Deine Spalten sind noch nicht allokalisiert...

Versuch mal folgendes:

```
6         unsigned char **image;
      7         image = new unsigned char*[SIZE];
      8 
      9         for(int i = 0; i < SIZE;i++){
     10                 *(image + i) = new unsigned char[SIZE*SIZE];
     11         }
```

@squeaker



> Deine Größen sind vielleicht konstant zur Laufzeit - können sich aber von Lauf zu Lauf ändern bzw. von Funktionsaufruf zu Funktionsaufruf.



Also das macht doch nix, weil wenn ein neuer Funktionsaufruf erfolgt, exisitiert das alte Array doch eh nicht mehr es wird ein neues angelegt welches für seine Lebensdauer
wieder statisch ist.


> Wegoptimiert heisst, dass der Code nicht in die exe geschrieben wurde, da der Compiler festgestellt hat, dass er nie ausgeführt wird.



Also bei mir existiert das Binary nach dem Kompilieren und es lässt sich ausführen und debuggen...

Gruß

RedWing


----------



## squeaker (13. Juli 2004)

> _Original geschrieben von RedWing _
> *@Holger:
> Also bei mir existiert das Binary nach dem Kompilieren und es lässt sich ausführen und debuggen...
> 
> RedWing *



Das habe ich nicht bezweifelt - aber ist auch der Code drin, den du geschrieben hast, sprich wird da wirklich der Array angelegt. Ein Compiler kreiert immer ein Binary - und sei es nur ein push 0 und der Call für das Beenden des Programms.


----------



## Dudadida (13. Juli 2004)

mach's mal so:


```
unsigned char **image;
image = (unsigned char **) malloc(spalten *sizeof(unsigned char*) ); 

for (int i =0; i < spalten; i++)
{
  image[i] = (unsigned char*) malloc(zeilen * sizeof(unsigned char));
}
```

so mach ich das immer und so geht's. die verteilung ist dann:
image[spalten][zeilen]
Wenn du es andersrum haben willst, musst du halt die Variablen vertauschen.

freigeben dann analog:

```
for (int i = 0; i < spalten;i++) free(image[i]);
free(image);
```


----------



## RedWing (13. Juli 2004)

Du hast recht der Methodendeinfition + aufruf von initArray exisitiert zwar aber auf das Feld kann ich nicht zugreifen(im Debugger).
Aber ich sehe trotzdem nicht was an folgender Lösung dirty bzw zu einem Fehler führen sollte und wieso das kein statisches Feld innerhalb der Methode sein sollte?

Code Example:


```
1 #include <iostream>
      2 
      3 using namespace std;
      4 void initArray(const int a, const int b){
      5         char feld[a][b];
      6 
      7         for(int i = 0; i < a; i++)
      8                 for(int j = 0; j < b; j++)
      9                         feld[i][j] = 'a';
     10         cout << feld[3][3] << endl;
     11 }
     12 int main(void){
     13 
     14         initArray(5,5);
     15 }
```


Gruß

RedWing


----------



## HolgerX (13. Juli 2004)

Also ich komme vom Java-Programmieren, und da ist es doch so einfach ein zwei-oder drei- oder n-Dimensionales Array anzulegen.

Jetzt muss ich aber leider mit C++ programmieren.
Jetzt habe ich dank der http://www.pixelate.co.za/issues/12/articles/dynamicarrays/dynamicarrays.html mitbekommen, wie man das in C++ bzw. C machen muss.

Da ich konsequent jedes C-Stil Programmieren vermeide werde ich bestimmt nicht mit *malloc* arbeiten!

Jetzt habe ich einen lauffähigen C++ Code geschrieben:
	
	
	



```
unsigned char **image;
	image = new unsigned char*[spalten];
	for(zeile = 0; spalte<spalten; spalte++)
	{
		image[spalte] = new unsigned char[zeilen];
	}

	for(zeile = 0; zeile<zeilen; zeile++)
	{	
		for(spalte = 0; spalte<spalten; spalte++)	
		{
			farbwert = input[zeile * spalten + spalte];
			image[spalte][zeile] = farbwert;						
		}

	}
```
 Fast hätte ich natürlich noch vergessen den Speicher wieder freizugeben, aber das mache ich natürlich auch noch! - Wie gut, dass es in Java einen Garbage-Collector gibt!

Danke an alle für Eure Mühe! 

*C sux!*


----------



## squeaker (13. Juli 2004)

Entschuldige - aber es war nicht klar ob C oder C++ programmiert werden soll.

Mit new sollte man aber auch ein 2dimensionales Array anfordern können, oder?


----------



## Kachelator (13. Juli 2004)

Nein, das muss man aus einem eindimensionalen new[] umbasteln.

Wenn C++, rate ich zu std::vector, oder noch besser in dem Fall: boost::multi_array (http://www.boost.org).


----------

