Nullterminierte Strings

Re: [OT] Noch eine frage anhängt

Ja, sie sind 2 Byte groß. Da mußt Du dann die wide-character-Funktionen (wsprintf, wscanf, ...) verwenden.
 
freakyjoe hat gesagt.:
tja ein 2 dimensionales ist in C ein Eindimensionales im Speicher
Das ist nicht zwingend so! Hängt ganz vom Compiler ab, wie er ein mehrdimensionales Array in den Speicher schreibt. Keine sichere Aussage kann man allerdings bei einem Array von nullterminierten String mit (zur Compilierzeit) unbekannter Länge treffen. Sukzessive Aufrufe vom malloc (o.ä.) garantieren nämlich nicht, aufeinanderfolgende Speicherbereiche zu reservieren.

Code:
i[j][k]=y;

wird eigentlich zu
Code:
*(i + j*10 + k)=y;
Nicht ganz, es würde wenn dann zu
Code:
*(*i + j*10 + k) = y;
werden.
Wobei es tatsächlich so ist, dass daraus
Code:
*(*(i + j) + k) = y;
entsteht (bei den mir bekannten Compilern zumindest).
 
Matthias Reitinger hat gesagt.:
Das ist nicht zwingend so! Hängt ganz vom Compiler ab, wie er ein mehrdimensionales Array in den Speicher schreibt. Keine sichere Aussage kann man allerdings bei einem Array von nullterminierten String mit (zur Compilierzeit) unbekannter Länge treffen. Sukzessive Aufrufe vom malloc (o.ä.) garantieren nämlich nicht, aufeinanderfolgende Speicherbereiche zu reservieren.

ganz recht, nur guck dir mal folgende Initialisierung an und sag mir, wie der Compiler das im Speicher "zerreißen" soll :-)

Code:
int x[2][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}};


er legt es ab der Speicherstelle auf die x (nicht *x) zeigt so ab 1 2 3 4 5 6 7 8
das ist amtlich in C (auch in C++)


Matthias Reitinger hat gesagt.:
Nicht ganz, es würde wenn dann zu
Code:
*(*i + j*10 + k) = y;
werden.
Wobei es tatsächlich so ist, dass daraus
Code:
*(*(i + j) + k) = y;
entsteht (bei den mir bekannten Compilern zumindest).

die Adresse des ersten Elementes von i[][] ist i und nicht *i also stimmt *(i+10*j+k) um den inhalt der Speicheradresse der j-ten zeile in der k-ten Spalte anzusprechen.

nettes Detail: es geht auch 3[ i ] um das 4. Element in einem eindimensionalen Array anzusprechen, da der []-Operator kommutativ ist! (nicht zu empfehlen, da schwer lesbar)

dass der + - Operator stärker bindet als der Deref-Op * wär mir neu ;-) aber ich werd mal nachgucken.

nun zu einer anderen Frage "Ist sizeof(char) immer 1?":
Ja. immer, immer. immer. Da char so definiert ist... als ein byte. Alles was sizeof liefert ist in byte-Einheiten. (man kann allerdings auch z.B. 9-bit breite Bytes definieren ... nur mal so als Anmerkung)

lg
Johannes
 
freakyjoe hat gesagt.:
ganz recht, nur guck dir mal folgende Initialisierung an und sag mir, wie der Compiler das im Speicher "zerreißen" soll :-)

int x[2][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}};

er legt es ab der Speicherstelle auf die x (nicht *x) zeigt so ab 1 2 3 4 5 6 7 8
das ist amtlich in C (auch in C++)
Nö, das ist Käse. x zeigt auf ein Array von zwei Zeigern. Diese zeigen wiederum auf jeweils ein Array mit vier Integer-Werten. Wo diese beiden Integer-Arrays liegen, ist dabei nicht festgelegt – sie können (und werden meistens auch) direkt hintereinander im Arbeitsspeicher liegen. Muss aber nicht zwingend sein. Würde mich interessieren, wo das „amtlich“ hinterlegt ist, dass das nicht so ist.

Kannst es ja selber testen:
Code:
int x[2][4] = { {1, 2, 3, 4}, {5, 6, 7, 8} };
printf("%d\n%d\n", *x, **x);

die Adresse des ersten Elementes von i[][] ist i und nicht *i also stimmt *(i+10*j+k) um den inhalt der Speicheradresse der j-ten zeile in der k-ten Spalte anzusprechen.
Wiederum falsch, sorry. Du hast hier ein Array von Zeigern, die auf Arrays von Integerzahlen zeigen. Die Adresse des ersten Elementes steht also in *i oder aber auch in i[0], wenn dir das lieber ist.

Kann man wiederum recht einfach überprüfen:
Code:
int i[10][10];
int j, k;
    
j = 2; k = 6;
    
i[j][k] = 1234;
    
printf("%d\n", *(i+10*j+k));
printf("%d\n", *(*i+10*j+k));
 
Also danke mal @all, die mir hier geholfen haben!
Auch wenn ich den Inhalt der aktuellen Diskussion hier nicht mehr versteh... :-)

MfG
DeChecka
 
Matthias Reitinger hat gesagt.:
Nö, das ist Käse. x zeigt auf ein Array von zwei Zeigern. Diese zeigen wiederum auf jeweils ein Array mit vier Integer-Werten. Wo diese beiden Integer-Arrays liegen, ist dabei nicht festgelegt – sie können (und werden meistens auch) direkt hintereinander im Arbeitsspeicher liegen. Muss aber nicht zwingend sein. Würde mich interessieren, wo das „amtlich“ hinterlegt ist, dass das nicht so ist.

So einfach ist das nicht!!

In: int x[10][10] ist x[] ein Objekt vom Typ "Array von 10 ints" und kein Pointer auf int!! er castet nur ohne Mucken auf int*.

x ist vom Typ int* aber da x[] ein Array von ints ist, und x[0] das erste Array ist, ist x == *x laut Definition von Arrays.

es ist definiert zu *(*(x+j)+k) (das stimmt, hab schlecht gelesen, sorry): Es wird zu (jetzt als Zahlen) (x+j*(sizeof(int)*10)) +k*sizof(int)

es funktioniert auch:

Code:
int i[10][10]={0};

int*x=i;

int j=3;
int k=6;

i[j][k]=1234;

printf("%d",*(x+10j+k));

was normalerweise sogar schnelleren Code erzeugt.

da i==*i ist, müsste auch (mein Fehler) *(i+10*j+k) funktionieren... nur der Typecast macht nicht mit.

also muss man schreiben *((int*)i+10*j+k)... da ja i vom typ "Array von 10 Arrays von 10 ints" ist (nicht! Pointer auf Pointer auf int)

Ein Array ist definiert als lineares Objekt (continous Object) im Speicher. JEDE Implementierung ist so geartet, dass die Elemente im Speicher hintereinander angeordnet sind.
Es ist dennoch möglich, dass z.B. ein Array eine Segmentgrenze überstreicht. Seit C99 ist auch das Verhalten hier angedacht worden. (Compiler können das verstecken, wenn sie wollen, oder warnen)

mit i[10][10]; wird
i[ j ][ k ]=1234; auf 32bit 80xx zu
Code:
imul        edx,j,0x00000028
mov         eax,k
shl         eax,0x02
add         eax,edx
mov         dword ptr -offsetof(i)[eax+ebp],0x000004d2
Das entspricht einer linearen Anordnung im Speicher.

Auch ist eine Initialisierung mit
int i[3][4]={1,2,3,4,1,2,3,4,1,2,3,4}; erlaubt.

Matthias Reitinger hat gesagt.:
Wiederum falsch, sorry. Du hast hier ein Array von Zeigern, die auf Arrays von Integerzahlen zeigen. Die Adresse des ersten Elementes steht also in *i oder aber auch in i[0], wenn dir das lieber ist.

Es ist kein Array von Zeigern ! Es ist ein "Array von Arrays von ints" (siehe Standard).

Zahlenmäßig gilt: i==*i==i[0] soviel zu dem Thema. Da jedoch immer andere Typen zutreffen, ist alles kompliziert.

Typ von i: Array von Arrays von 10 ints.
Typ von *i:Array von 10 ints.
Typ von i[0]:Array von 10 ints.

lg
Johannes
 
Zuletzt bearbeitet:
Zurück