argv, Zeigerarrays und andere Widrigkeiten ;o)
-
Original erstellt von <fff>:
das letzte is 16 byte grossBrrr, natürlich. Muss jetzt mal ins Bett, ich nehme schon für int 2 Bytes an *ggg*.
@volkard: der Unterschied zwischen Zeigerarrays und richtigen Arrays, die Arrays enthalten ist mir schon klar, aber es lassen sich doch Arrays trotzdem mit Zeigern abbilden...
Hm, ich denke morgen früh noch einmal drüber nach, heute bringt das nix mehr.
-
Naja also wenn du mit alten Windows-Versionene arbeitest, sind 2Byte schon richtig
-
Original erstellt von RTC:
@volkard: der Unterschied zwischen Zeigerarrays und richtigen Arrays, die Arrays enthalten ist mir schon klar, aber es lassen sich doch Arrays trotzdem mit Zeigern abbilden...es ist eher so, daß bezeichner, die arrays bezeichnen, automatisch in einen zeiger aufs erste element ausgewertet werden, wenn der bezeichner nicht direkt als array verwendet werdne kann, was höchst selten ist. z.B. in sizeof. die operatoren * und [] arbeiten schlicht auf zeigern.
mal wieder was spielen:
int a[3][4];//a ist array von 3 arrays von je 4 ints.
beachte, daß a[1] um 16 bytes weiter hinten liegt als a[0].und jetzt lege ich ein zeigerarray an, was auf die drei sub-arrays zeigt.
int *b[3]={a[0],a[1],a[2]};//b ist array von 3 zeigern auf int.
normalerweise hätte ich die drei subarrays mit malloc angelegt.
beachte, daß b[1] nur um 4 bytes weiter hinten liegt, als b[0].und jetzt lege ich einen zeiger an, der das auch kann.
int (*c)[4]=a;//c ist zeiger auf arrays von je 4 int.
beachte, daß a[1] um 16 bytes weiter hinten liegt als a[0].wenn ich also hart aus nem int a[3][4] ein int **a machen würde, gäbe es mit den arrayzugriffen nur fehler.
das einzige, was die gemein haben ist, daß man auf beide mit x=a[2][1] zugreifen kann. sie fühlen sich beide wie 2-dimensionale arrays an (und meiner philosophischen grundhaltung nach sind sie daher wenigstens teilweise 2-dimensionale arrays).
-
Also ist Zeiger auf Zeiger eigentlich schwachsinn oder?
-
Original erstellt von <fff>:
Also ist Zeiger auf Zeiger eigentlich schwachsinn oder?nee. ist nur anderes speicherlayout.
int** mach2darray(int sx,int sy) { int i; int** oberarray=malloc(sx*sizeof(int*)); for(i=0;i<sx;++i) oberarray[i]=malloc(sy*sizeof(int)); return oberarray; }
vorteil von das hier ist, daß der ganze speicher nicht an einem stück sein muß, was bei dos manchmal schwer war. und daß der benutzer dieses 2d-arrays nix über dessen dimensionen wissen muß. die beiden dereferenzierungen bei zweimaligem [] machen das schon.
int (*mach2darraymitsyist4(int sx))[4] { int (*array)[4]=malloc(sx*sizeof(int[4])); return array; }
vorteil von das hier ist, daß nicht zwei dereferenzierunge nötig sind, sondern ein [] mit adresberechnung gemacht wird. und ein wenig speicherplatzsparender ist es, weil kein oberarray gebaurcht wird. und natürlich nur ein malloc-aufruf. nachteil ist, daß nur eine dimension frei wählbar ist. alle anderen müssen fest sein.
-
Wielange hast Du den gebraucht, um das mit den "Zeiger auf Zeiger" zu verstehen?
-
Original erstellt von <fff>:
Wielange hast Du den gebraucht, um das mit den "Zeiger auf Zeiger" zu verstehen?jahre.
-
Das ist häftig.
Auf jeden Fall danke, für deine Hilfe.
-
Original erstellt von fff**
Naja also wenn du mit alten Windows-Versionene arbeitest, sind 2Byte schon richtig**Nix altes Windows, sondern neues Linux
Aber ist schon klar, das mit den 16Bit. 32Bits sind natürlich 4 Bytes...Original erstellt von volkard**
jahre.**Ich sehe mich auch in ein paar Jahren noch dahängen und darüber grübeln, ob es nun ein Zeigerarray oder sonst was anderes ist *kotz*. Mal im Ernst: ich habe noch keine Anleitung gesehen, in der das einfach verständlich erklärt wird. Aber es kann bestimmt nicht deshalb einfach erklärt werden, weil es nicht einfach ist - ganz einfach
Ok, ich resümiere mal für mich: Zeigerarrays, deren Elemente wieder auf Arrays zeigen, sind natürlich keine 2-dim-Arrays, da 2-dim-Arrays als Elemente wiederum Arrays enthalten und ihr Speicherplatz hintereinander reserviert ist. Die Arrays, auf die die Elemente eines Zeigerarrays zeigen, können hingegen dynamisch verändert werden, das ganze Array von Zeigern kann natürlich auch dynamisch verändert werden, wenn man eine Dimensionierung unterlässt und malloc zunächst auf das Zeigerarray und dann noch auf jedes Array, auf welches ein Zeiger des Zeigerarrays zeigt, ausführt.
Aber: Zeigerarrays, deren Elemente auf Zeiger zeigen UND 2-dim-Arrays können auf dieselbe Art und Weise angesprochen werden, oder?Letzter Hint hierzu nochmal: wieso darf ich argv++ ausführen, wenn doch argv ein konstanter Zeiger ist? Bashar hatte eine kleine Lösung angegeben, doch damit kann ich wenig anfangen: "Weil Array an Funktionen als Zeiger übergeben werden."
Kann mir das jemand nochmal kurz erklären?
-
Kennst Du schon das Tutorial auf www.pronix.de ?
Da wird das und noch viel mehr, verständlich und leicht erklärt
Nix altes Windows, sondern neues Linux
dito
-
Kenne es schon, aber da habe ich in Bezug auf die kleine argv-Frage keine Antwort gefunden
-
Original erstellt von RTC:
Letzter Hint hierzu nochmal: wieso darf ich argv++ ausführen, wenn doch argv ein konstanter Zeiger ist? Bashar hatte eine kleine Lösung angegeben, doch damit kann ich wenig anfangen: "Weil Array an Funktionen als Zeiger übergeben werden."
Kann mir das jemand nochmal kurz erklären?also sowas:
int main(int argc,char** argv) { ++argv; return 0; }
tja, also argv ist hier nicht konstant. ist ne lokale variable, die auf den ersten argument-string zeigt. so nen übergebenen zeiger kannste ändern. macht man manchmal auch ganz gerne, wie hier:
int strlen(char* str) { int result=0; while(*str) { ++result; ++str; } return result; }
gemeiner wirds hierbei:
int main(int argc,char *argv[]) { ++argv; return 0; }
das darf natürlich nicht klappen. außer, bashar hat nen guten grund.
erstmal seine these prüfen, daß da heimlich nu ein zeiger übergeben wird.
void test(double x[]) { cout<<sizeof(x)<<endl; } int main() { double a[10]; cout<<sizeof(a)<<endl; test(a); return 0; }
ausgabe:
80 4
aha. durch irgend eine compilermagie wurde in der tat dafür gesorgt, daß x innerhalb der funktion nur ein zeiger ist. hat vermutlich den grund, daß es viel zu lange dauern würde, alle 80 bytes zu kopieren bei jedem funktionsaufruf.
wenn ich jetzt ganz fest an die compilermagie glaube, ganz fest daran, daß da in wirklichkeit statt void test(double x[]) nur ein void test(double *x) steht, dann klappt ++x.
-
Original erstellt von volkard:
**also sowas:int main(int argc,char** argv) { ++argv; return 0; }
tja, also argv ist hier nicht konstant.
[...]
gemeiner wirds hierbei:int main(int argc,char *argv[]) { ++argv; return 0; }
das darf natürlich nicht klappen. außer, bashar hat nen guten grund.**
Bin zwar nicht bashar, aber ich antworte trotzdem mal
Beide Beispiele sind äquivalent.
"A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation." (ISO/IEC 9899:1999, 6.7.5.3-7)
int main(int argc,char argv[])
wird also so ausgewertet, als würde da
int main(int argc,char* argv)
stehen.
-
Ok danke!
Das hat mir erstmal weiter geholfen.
Thx a lot...