[C++]angeforderter speicherbereich zusammenhängend?

hackebeil

Cadet 4th Year
Registriert
Nov. 2004
Beiträge
75
ich mache mir für mein programm mit diesem code ein array für eine bildebene:
Code:
pixel = new int*[x];
for (int i = 0; i < x; ++i){
    pixel[i] = new int[y];
}

ist der speicher den ich da bekomme ein durchgehender bereich?

ich frage weil ich vorhabe diverse funktionen des programms zu beschleunigen indem ich die pixel nicht über ihre koordinaten anspreche sondern einfach einen pointer um den entsprechenden wert für den nächsten pixel erhöhe

beispiel:
array hat die größe 5x5
statt:
Code:
for(int i = 0; i < 5; ++i){
    for(int j = 0; j < 5; ++j){
        pixel[j][i]=1;
    }
}
Code:
int* pointer = &pixel[0][0];
for(int i = 0; i < 5*5; ++i){
    *pointer = 1;
    pointer++;
}
 
Die idee hatten andere auch schon vor dir. um genau zu sein die erfinder von C :P. C Arrays sind eigentlich nur ein pointer auf das erste array element und der [] operator macht nichts anderes als das was du da manuel vor hast - nur mit einer anderen syntax.

es bringt also absolut nichts. sinnvoller wäre für solche bitmaps allerdings sowieso ein stl container. mit solchen uralt arrays ist der nächste speicherfehler nicht weit entfernt, und das optimieren mit solchen mitteln ist praktisch fast nie sinnvoll(die stl wurde je nach compiler schließlich schon von profis erstellt. das du eine schnellere implementierung hinbekommst ist wohl relativ unrealistisch ;)).
 
Zuerstmal, um die Frage zu beantworten: Die Speicherbereiche sind pro new zusammenhängend. Darum kann das, was du da vorhast auch garnicht gehen. Außerdem wäre deine "Optimierung" mit sehr großer Wahrscheinlichkeit langsamer, als hätte man ein blankes Array von int x[5][5].

Egal, welches davon schneller ist, ich bezweifle, dass dieser Code auch nur annähernd die Rechenzeit deines Programmes dominiert. Hast du einen Profiler genutzt um zu gucken, wo das Programm langsam ist? Ein "Schuss ins blaue" ist quasi immer sinnlos und der Einsatz eines Profilers gibt sehr oft Überraschungen, wo die Rechenzeiten tatsächlich bleiben.

Nur mal als kleines Beispiel: Stünde dein Code mit den new's und der Schleife zum Befüllen direkt hintereinander, so würde die new-Aufrufe wohl ca. 99% der verbrauchten Zeit ausmachen. Überlass dem Compiler solche Mikrooptimierungen wie Schleifen. Die können ge'unrollt' werden, können speziell im Speicher ausgerichtet werden etc. und machen den Code wirklich flink. Durch eigene vermeintliche Optimierungen machst du dem Compiler sein Optimierungspotenzial meist kaputt und der Code wird langsamer.


Btw, es gibt keinen Grund zu der Annahme, dass das "Drüberlaufen" über ein Stück Speicher mit einem Zeiger schneller wäre als der Zugriff mit dem []-Operator.


@Siberian..Husky: Arrays mit Pointern gleichzusetzen ist ein Kardinalsfehler. :) C-Arrays sind ein Stück Speicher. Spätestens wenn du bei extern-Deklarationen Array- und Pointer-Syntax vermischt, gibt das die wildesten Fehler. Arrays konvertieren zwar bei der kleinesten Kleinigkeit implizit in einen Pointer auf ihr erstes Element, aber sind sind trotzdem immer ein Stück Speicher.
 
grml... man sollte natürlich den code ganz genau lesen. mit 2 arrays funktioniert das so natürlich nicht...


@ 7H3 N4C3R:
bist du dir da ganz sicher? soweit ich weiß sind c arrays nichts anderes als pointer. für einen speicherbereich müsste schließlich der anfangs und endpunkt gespeichert werden - das passiert bei C Arrays aber aufjedenfall nicht(sonst könnte der compiler ja den gültigkeitsbereich des indexes überprüfen...).

EDIT: eigentlich sollte aus array genau der selbe code generiert werden wie aus *(array + i).
 
Zuletzt bearbeitet:
@Siberian..Husky:
Ganz sicher. :)

Beispiel:

a.cpp:
Code:
int a[20];

b.cpp
Code:
extern int* a; // Falsch! Produziert ganz fiese Fehler

Sobald ein Array in ein T[] konvertiert oder in einen Zeiger auf sein erstes Element, steht an anderer Stelle natürlich keine Information über die Länge mehr zur Verfügung.
 
also laut Stroustrup ist ein C array eigentlich absolut kaputt ;). zwar gibt es einen echten array type, aber den kann man nicht benutzen - jedesmall wenn man ein array benutzen will wird automatisch in ein pointer konvertiert. ausserdem wird wohl die länge gespeichert(da er wie du auch schreibt das diese information verloren geht) - allerdings habe ich keine ahnung wo man diese länge nutzen können soll...

ausserdem ist es wohl völlig egal ob man array oder *(array + i ) benutzt...


blos gut das man bei C++ auf solche krücken nichtmehr angewiesen ist.

EDIT: ob die länge bei arrays gespeichert und genutzt wird kommt wohl auf die C(++) implementierung an. ist wohl nicht im standard festgelegt...
 
Zuletzt bearbeitet:
@Siberian..Husky:
Das mit der Länge ist völlig unproblematisch, sofern diese noch bekannt ist:

Code:
#include <iostream>

...

/// richtig:
int a[20] = {};
std::cout << "Das array ist " << sizeof(a) / sizeof(int) << " Felder gross" << std::endl;


/// falsch, nicht nachmachen:
void f( int a[]) // oder alternativ void f( int* a)
{
   std::cout << "Das array ist " << sizeof(a) / sizeof(int) << " Felder gross" << std::endl;
}
(der Code ist standardkonform)


Und ob array oder *(array + i) ist ziemlich egal. Allerdings ist die Form mit [] intuitiv leichter verständlich.
 
Zuletzt bearbeitet:
wenn ihr schon über möglichkeiten der array-adressierung in c streitet, habt ihr die beste noch vergessen:
index[array]

einer der lustigsten designfehler in c.
 
schönen dank für die antworten
zum thema:
ich benutze keine container aus der stl weil es ein schulprogramm ist und wir selbige praktische hilfsmittel dort nicht nutzen sollen
es soll alles von hand gebastelt werden

und statt *(array + i) dachte ich an dinge wie array += zeilenlänge+1 um ein feld nach rechts UND unten zu gehen

aber das ist wohl auch recht egal wenn es keinen signifikanten unterschied macht
 
ghorst schrieb:
wenn ihr schon über möglichkeiten der array-adressierung in c streitet, habt ihr die beste noch vergessen:
index[array]

einer der lustigsten designfehler in c.

Naja, Fehler oder nicht weiß ich nicht. Ich dachte, das wäre aber auch nur für 0 definiert? Hab zwar den C++-Standard zur Hand, aber keine Ahnung wo ich jetzt anfangen sollte zu suchen. :) Naja, und in Anbetracht der Uhrzeit auch keine Lust mehr. *g*

Aber ob ich von p aus um 0 Stellen verschiebe oder von 0 aus um p Stellen ist ja von der Logik her erstmal egal. ^^ Daraus lassen sich witzige Konstrukte machen wie "#$24"[4][p] :)

Edit:
Hab's mal nachgelesen: Beim (eingebauten) []-Operator in er Form E1[E2] muss eines von beiden ein Zeiger sein und das andere ein integraler Wert. Per Definition ist das äquivalent zu *(E1+E2). Aufgrund des +-Operators ist die Reihenfolge egal.
 
Zuletzt bearbeitet:
7H3 N4C3R schrieb:
genau diese mischung der beiden verfahren macht es für mich zu einem designfehler. wenn man nur einen von beiden nutzt, ist es egal welchen man nimmt. nur hat sich die variante array[index] mehrheitlich durchgesetzt und index[array] wird eigentlich nur benutzt, um code unverständlich zu machen oder zu zeigen, dass c dinge kann, die lustig sind ^^, daher sollte man index[array] aus dem standard rausschmeißen.
das index[array] und arrray[index] auf grund einer möglichen makronutzung, die gleiche bedeutung haben, spielt da für mich nur eine nebenrolle. das, das als makro aufgelöst wird, dürfte heute nicht mehr nötig seien.

EDIT danke für das gute bsp. hier noch mal die auflösung, wie man das lesen muss: "#$24"[4] ist der zugriff auf das 5. element des strings. also 0, da ein string ist null-terminiert ist. das ergibt 0[p] also gleich *p. noch fragen?
 
Zuletzt bearbeitet:
Zurück
Oben