# Nullterminierte Strings



## DeChecka (4. Juli 2005)

Hi!
Kann ich in einem char-Array auch mehrere '\0' s haben?
Also zum Beispiel: 'h', 'a', 'l', 'l', 'o', '\0', 'g', 'u', 't', 'e', 'n', 't', 'a', 'g', '\0' ...

MfG
      DeChecka


----------



## C Coder (4. Juli 2005)

Natürlich kannst du das machen - aber sämtliche Funktionen lesen dann nur bis zur *1.* Terminierung und machen danach schluss!

also in deinem Beispiel würde ein printf aufruck folgendes ausgeben:
*Hallo* und dann ist ende!


----------



## thooomy (5. Juli 2005)

ja ich weiss so eine frage nervt,. aber wozu willst du das eigentlich machen ?
Egal was du vorhast - es gibt bestimmt einen besseren weg


----------



## jokey2 (5. Juli 2005)

Es gibt allerdings auch Stringlisten, die lauter nullterminierte Strings hintereinanderhängen und die Liste mit einer zusätzlichen 0 abschließen, z. B., wenn Du die Umgebungsvariablen unter Windows ausliest.
 Beispiel:
	
	
	



```
char Begruessungen[] = {'H', 'a', 'l', 'l', 'o', 0, 'G', 'u', 't', 'e', 'n', ' ', 'T', 'a', 'g', 0, 'G', 'u', 't', 'e', 'n', ' ', 'A', 'b', 'e', 'n', 'd', 0, 0};
```


----------



## DeChecka (5. Juli 2005)

Naja... ich will bestimmte Wörter nicht in nem zweidimensionalen Array speichern, sondern in nem eindimensionalen, da mir das für meine Zwecke einfacher erscheint  ...

Das mit dem Abschneiden der Zeichen nach dem ersten '\0' ist mir bewusst, das löse ich anders...

Nur mein Prog funktionierte nicht so, wie es sollte, deshalb wollt ich mich mal vergewissen...

Also danke mal allen! Der Fehler muss dann wohl woanders liegen.

MfG
      DeChecka


----------



## Tobias K. (5. Juli 2005)

moin


Poste den Code mit ner Beschreibung was es machen woll, dann kann dir sicher schnell geholfen werden.


mfg
umbrasaxum


----------



## freakyjoe (5. Juli 2005)

DeChecka hat gesagt.:
			
		

> Naja... ich will bestimmte Wörter nicht in nem zweidimensionalen Array speichern, sondern in nem eindimensionalen, da mir das für meine Zwecke einfacher erscheint  ...
> 
> Das mit dem Abschneiden der Zeichen nach dem ersten '\0' ist mir bewusst, das löse ich anders...
> 
> ...



tja ein 2 dimensionales ist in C ein Eindimensionales im Speicher

```
int i[10][10];

i[j][k]=y;
```

wird eigentlich zu
	
	
	



```
*(i + j*10 + k)=y;
```
 (Zeiger - Feld dualität... mit implizitem Typecast von int auf sizeof(int) da ja j und k ints sind aber i ein Zeiger auf int)

es ist nur einfacher zu schreiben
	
	
	



```
i[j][k]=y;
```


wenn die Strings unterschiedlich lang sind: mit 
	
	
	



```
char* Stringarray[10];
```
 und dann 
	
	
	



```
Stringarray[0]=(char *)malloc(DynamischeLaenge * sizeof(char));
```
 sizeof(char) kann entfallen, da es per definition 1 ist.

auf das Abfragen nicht vergessen und das Freigeben, es freut sich sonst Mr. Memoryleak

lg
Johannes


----------



## thooomy (6. Juli 2005)

freakyjoe hat gesagt.:
			
		

> sizeof(char) kann entfallen, da es per definition 1 ist.



is zwar OT, aber ist das wirklich so ? .. also klar das es fast überall eins ist (ich würde auch nichts anderes annehmen), aber laut welcher definition ist es 1 ?

ich verwende i.a. sizeof(char), wusste aber bisher nie ob es irgendwann ne rolle spielt - gibt es systemumgebungen wo es nicht so ist ?....


----------



## Tobias K. (6. Juli 2005)

moin


Ja das ist richtig. Ein char ist ein Byte groß, genauso wie ein unsigned char.


mfg
umbrasaxum


----------



## Lemiras (7. Juli 2005)

*Re: [OT] Noch eine frage anhängt*

Mal rein interessenhalber, wie schaut es eigentlich dabei mit UNICODE kodierten Strings aus, gibt es dafür regeln oder muß man sich sowas selber zusammenbasteln, denn damit würden ja ein Zeichen nicht mehr ein Byte belegen. (Habe grad nicht in Kopf mit wie vielen es Kodiert ist ich glaube 2 oder?)

Gruß Lemi


----------



## jokey2 (7. Juli 2005)

*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.


----------



## Matthias Reitinger (7. Juli 2005)

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.


```
i[j][k]=y;
```

wird eigentlich zu 
	
	
	



```
*(i + j*10 + k)=y;
```
Nicht ganz, es würde wenn dann zu 
	
	
	



```
*(*i + j*10 + k) = y;
```
 werden.
Wobei es tatsächlich so ist, dass daraus 
	
	
	



```
*(*(i + j) + k) = y;
```
 entsteht (bei den mir bekannten Compilern zumindest).


----------



## freakyjoe (8. Juli 2005)

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 


```
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
> 
> 
> 
> ...



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


----------



## Matthias Reitinger (9. Juli 2005)

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}};
> 
> ...


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:
	
	
	



```
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:
	
	
	



```
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));
```


----------



## DeChecka (11. Juli 2005)

Also danke mal @all, die mir hier geholfen haben!
Auch wenn ich den Inhalt der aktuellen Diskussion hier nicht mehr versteh...  

MfG
      DeChecka


----------



## freakyjoe (11. Juli 2005)

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:


```
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

```
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


----------

