Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Der beste Weg Arrays zu erstellen?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
29.09.2003, 16:52 Uhr
Pablo
Supertux
(Operator)


Angeommen muss ich ein n-dim. Array erstellen. Beschränken wir auf n=2

Es gibt dann 4 Möglichkeiten.

Ich kenne die Länge beide Arrays, dann muss ich so machen.

C++:
typ varname[LAENGE1][LAENGE2];



Ich kenne keine der beiden, und die Variablen x und y haben sie.
Ist das am besten so?

C++:
typ **varname;
varname = malloc(sizeof(typ*)*x);
if (varname==NULL) // mist kein Speicher
...
for(i=0;i<x;++i) {
    varname[i] = (typ*) malloc(sizeof(typ)*y);
    if(varname[i] == NULL) //mist kein Speicher mehr
        unternehme_etwas_dagegen();
}



Eine der beiden Längen ist bekannt. Wie macht man das am besten?
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.09.2003, 17:14 Uhr
~nAvi
Gast


Kann man da nicht auch mit const arbeiten?
Is sicher nicht so elegant wie mit malloc aber es müsste gehen.

zB so:

C++:
const int x1 = x;
const int y1 = y;

typ varname [x1] [y1]

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.09.2003, 18:52 Uhr
0xdeadbeef
Gott
(Operator)


Es sind ja Variablen. Also, die ersten beiden sind so schon sinnvoll. Wenn eine der beiden Dimensionen bekannt ist, würde ich sowas machen:

C++:
typ *varname[BEKANNTE_LAENGE];


und dann entsprechend per malloc Speicher zuweisen. Wenn du keine Lust auf die umständliche mallocerei hast, geht auch folgendes:

C++:
typ *varname = malloc(sizeof(typ) * x * y);
varname[2 * y + 1] = 3; /* statt varname[2][1] */


...allerdings wird da natürlich nachher das dereferenzieren sehr widerlich. Sowas kann man eigentlich nur dann sinnvoll machen, wenn du das Ding direkt danach an eine Funktion weitergibst. Da kannst du dann nämlich folgendes machen:

C++:
void foo(int x[BEKANNTE_LAENGE][]) {
  x[2][1] = 3;
}


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
29.09.2003, 18:56 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)



Zitat:

...das dereferenzieren sehr widerlich...


Ich vesteh nicht was an zählervariable mal "arraybreite" hinzuaddieren so wiederlich sein soll
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
29.09.2003, 19:07 Uhr
0xdeadbeef
Gott
(Operator)


Versuch das mal zu debuggen, wenn du dich irgendwo vertippst. Da kriegst du die schönsten Heisenbugs. Und du musst dir die ganze Zeit die Array-Breite merken. Dabei ist es so verlockend, das x wiederzuverwenden...

Es gibt viele Möglichkeiten, damit Mist zu bauen, vor allem, wenn nachher jemand anders den Code auch noch verstehen soll.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 29.09.2003 um 19:11 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
29.09.2003, 19:24 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


Heisenbugs was ist das?

Also wie du sicherlich gemerkt hast mach ich das nach möglichkeit immer mit 1d-arrays und bin damit recht zufrieden. Ich finde es besser weil ich es hasse immer ne schleife mitzuschleppen um das am ende wieder freizugeben. Besonders bei 3d-und grösser sehr nervend
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
29.09.2003, 19:51 Uhr
virtual
Sexiest Bit alive
(Operator)


Mein Meinung dazu (falls sie jemanden interessiert):
Es gibt hier keinen Königweg. Es sind meiner Meinung nach zwei wesentliche Aspekte zu beachten.
1. Speicherlayout
Wird Ein Array statische deklariert, etwa so:

C++:
int array[10][10];


so liegen alle Elemente dieses Arrays in einem zusammenhängenden Speicherbereich. Wenn man das gleiche Array dynamisch haben will, darf man folglich nicht mehr als ein malloc Machen und man muß die Referenzierung der einzelnen Elemente per hand machen, weil malloc nun mal nur eindimensionale Arrays zurückgibt.
2. Ansprechen einzelnen Elemente
Steht mehr im Vordergrund, eine bequeme Referenzierung der einzelnen Array elemente zu haben, dann wird man kaum umhinkommen, einen Ansatz zu wählen, wie ihn Pablo vorgeschalgen hat (Array als array von Speicherbereichen ansehen). Das kann durchaus sinnvoll sein.

Die Frage, was nun sinnvoll ist, hängt meiner Meinung nach von dem jeweiligen Problem ab, wenn ich nach einer pauschalen Meinung gefragt wäre, würde ich aber ein einfaches Malloc vorziehen, weil:

1. Elemente liegen in einem zusammenhängenden Speicherbereich, Operationen, die auf jedes Elemente unabh. von ihrer Lage in dem Array wirken, lassen sich also leichter Implementieren (nur eine Schleife an Stelle von zwei).

2. Erzeugen und Freigeben des Arrays ist deutlich einfacher als bei der unter 2 genannten Lösung.

3. Erzeugen und Freigeben des Arrays ist meßbar performanter als bei der unter 2 genannten Lösung, gleiches gilt für die Vergrößerung und verkleinerung des Arrays

4. Es ist weniger Speicherintensiv

Zwar sehe ich auch den Nachteil, daß es komplizierter ist, auf die einzelnen Elemente direkt zuzugreifen, aber das ist in meinen Augen noch verkraftbar (die von Beefy angeprochenen Heisenbugs können eigentlich nur dann auftreten, wenn man die Dimensionen vertauscht; eine Sache, die man auch bei einem Statischen 2D Array falsch machen kann.).

Wenn viele Arrays verschiedener Größe benutzt werden, empfiehlt sich eh, einen entsprechende Struktur mit passenden Accessorroutinen zu machen. Wiederverwendbarer Code sollte eben auch in C kein Fremdwort sein...
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
29.09.2003, 21:56 Uhr
Pablo
Supertux
(Operator)


Bravo, danke an euch. Ich hatte schon mal die selbe Idee wie @virtual und @beefy,a ber ich war mir nicht so ganz sicher.

Also, die zwei andere Fälle, wenn

3. Ich kenne die zweite Dimension, die erste ist mir unbekannt.
Da würde genauso wie @beefy. Für mich sieht das so aus, als wäre varname[unbekannt][bekannt].

C++:
typ *varname[BEKANNTE_LAENGE];



Wenn ich so deklariere, heißt das, dass die erste Dimension unbekannt ist und mit malloc eine Größe zuordnen muss? Oder heißt es, dass die erste Länge bekannt und die zweite die unbekannte ist? Wie wäre es damit?

C++:
typ (*varname)[BEKANNTE_LAENGE];


Ich hab mal das schon kompiliert, aber ich konnte nicht initialisieren. Was ist denn das überhaupt? Ist das erste Dimension unbekannt und 2 bekannt?
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
29.09.2003, 23:45 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


@virtual
Wegen Punkten 1-3 hab ich das immer mit nem 1D-array gemacht und deine Ausführungen sagen mir das ich auch bei dieser Philosophie bleiben sollte/werde

Punkt 4 ist mir nicht klar. Warum ist es weniger speicherintensiv.

Vorteil bei beefys bevorzugter methode ist meiner meinung noch das es wahrscheinlicher ist das man den geforderten Speicher auch wirklich erhält


@beefy
und was ist nun genau ein Heisenbug hab ich immer noch nicht verstanden
--
...fleißig wie zwei Weißbrote

Dieser Post wurde am 29.09.2003 um 23:45 Uhr von Windalf editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
30.09.2003, 08:15 Uhr
virtual
Sexiest Bit alive
(Operator)


@Windalf
1. Heisenbug

2. Naja, wenn ich ein Array so aufbaue:

C++:
int** array = (int**)new int[100];
for(int i=0; i<100; ++i)
{
     array[i] = new int[100];
}


oder so

C++:
int* array = new int[100*100];


Dann macht das schon einen Unterschied. Im Letztern Fall ist der Speicherbedarf 10000*sizeof(int)+Overhead für Speicherblock. Sagen wir mal sizeof(int)==4 und der Overhead liegt oft bei 12 byte; also 40012 Bytes.
Im Zweiten Fall sind es:
100*(100*sizeof(int)+Overhead)+100*sizeof(int*)+Overhead Also etwa 100*412+400+12 = 41200+412=41612. In diesem Fall also >4% mehr Speichebedarf.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: