char initialisierung in C

Gast #4258588
Lesenswert?
• ▲
▼
Hi,

Ich lese gerade "Softwareentwicklung in C"
http://www.asc.tuwien.ac.at/eprog/download/schmaranz.pdf

Auf Seite 37 wird ein unsinged char folgendermassen initialisiert:
1
unsigned char a_uchar_= '\0';

Aus welchem Grund wird ein char mit Anfürungszeichen und mit einer 
Escape Sequenz initialisiert ?
1
unsigned char a_uchar_= 0;

Bewirkt doch das selbe, oder nicht ?


Mfg Koe
Gast #4263593
Lesenswert?
• ▲
▼
Dirk B. schrieb:
> Hier ist das aber etwas merkwürdig, da man für Zeichen  nur char als
> Typ verwenden sollte.

Das Buch ist alt und enthält selbst für sein Alter ziemliche 
oldschool-Konstrukte. Im Vorwort wird zwar darauf herumgeritten, dass es 
um sinnvolle Software-Entwicklung geht und nicht nur um das C-Lernen, 
aber es kommen ständig Kracher wie
1
main()
2
{
3
  printf( "Hello World!\n");
4
}
,
1
#define SWAP(a, b) {int swap = a; a = b; b = swap;}
oder Beispielprogramme, die ausschließlich (unnötig) globale Variablen 
enthalten, vor.
#4263598
Lesenswert?
• ▲
▼
In der Tat ist es sinnvoll, char zu verwenden und nicht signed oder 
unsigned char, solange man wirklich Zeichen damit speichern will.
Schon aus dem einfachen Grund, weil alle einschlägigen 
Bibliotheksfunktionen nicht signed oder unsigned char, sondern halt char 
verwenden und man unnötiges Casten und Gemecker vermeidet.

signed char oder unsigned char macht nur Sinn, wenn man den Typ nicht 
für Zeichen benutzt, sondern konkret damit rechnet, also einfach als 
kleine Zahl nutzt.
Ob der Name des Datentyps sinnvoll ist, sei dahingestellt - ist halt so.
Gast #4263602
Lesenswert?
• ▲
▼
Marc D. schrieb:
> Koe schrieb:
>
>> unsigned char a_uchar_= '\0';
>> unsigned char a_uchar_= 0;
>
>> Bewirkt doch das selbe, oder nicht ?
>
> NEIN,
> das eine ist 0x00 oder auch bekannt als NULL,
> das andere ist 0x30 ASCII für die Zahl Null.
>
> Damit ist es ein Unterschied.

wo sieht du hier ein  "0x30 ASCII für die Zahl Null"??
Gast #4263657
Lesenswert?
• ▲
▼
Marc D. schrieb:
> NEIN,
> das eine ist 0x00 oder auch bekannt als NULL,
> das andere ist 0x30 ASCII für die Zahl Null.
>
> Damit ist es ein Unterschied.

Unfug, erst selbst C lernen.
S.J. hat es korrekt formuliert.

unsigned char a_uchar_= '0';
würde die Variable mit 0x30 für die ZIFFER NULL initialisieren.
Gast #4263943
Lesenswert?
• ▲
▼
Dirk B. schrieb:
> Sonst: möglicherweise. Das ist Darstellungssache. (Wie wird das
> Bitmuster als Zahlenwert interpretiert)

Logisch. Letztendlich sind Strings nur Zahlenarrays die als ASCII 
interpretiert werden. Ich verwende dafür immer ein u8.

Warum sollte man da signed verwenden?
Gast #4264488
Lesenswert?
• ▲
▼
>> Gibt es auch negative (ASCII-)Zeichen?
>Bei ASCII: nein.

Die USA benutzen nur 7 Bit - ob das 8. Bit als negative Zahl 
interpretiert wird ist denen egal. In Deutschland wird das 8. Bit für 
Umlaute benutzt.

Der größte Murks, den jemals ein Amerikaner erfunden hat.
1
int[] characterType = {....};
2
char c = getc();
3
int type = characterType[c];

Funktioniert mit 7 Bit Ascii einwandfrei. Ob es in Deutschland 
funktioniert, hängt davon ab, ob der Compiler char als signed oder 
unsigned behandelt.
Gast #4264537
Lesenswert?
• ▲
▼
So ein verdammter Murks schrieb:
>>> Gibt es auch negative (ASCII-)Zeichen?
>>Bei ASCII: nein.
>
> Die USA benutzen nur 7 Bit - ob das 8. Bit als negative Zahl
> interpretiert wird ist denen egal. In Deutschland wird das 8. Bit für
> Umlaute benutzt.

Kommt drauf an was für ein Zeichensatz verwendet wird. Die gängigen 
(UTF-8 und UTF-16) brauchen 2 Byte für Umlaute. ISO-Codepages sind eher 
Altlasten die nicht mehr verwendet werden sollten.
#4264552
Lesenswert?
• ▲
▼
Matthias L. schrieb:
> Dirk B. schrieb:
>> Sonst: möglicherweise. Das ist Darstellungssache. (Wie wird das
>> Bitmuster als Zahlenwert interpretiert)
>
> Logisch. Letztendlich sind Strings nur Zahlenarrays die als ASCII
> interpretiert werden. Ich verwende dafür immer ein u8.
>
> Warum sollte man da signed verwenden?

Man benutzt weder explizit signed noch unsigned, sondern einfach nur 
char. Was der Compiler dafür als interne Repräsentation verwendet, kann 
einem völlig egal sein, da man damit sowieso nicht rechnet.
Also ist ein char mit Vorzeichen genauso sinnvoll oder sinnlos wie einer 
ohne.

So ein verdammter Murks schrieb:
> Der größte Murks, den jemals ein Amerikaner erfunden hat.
> int[] characterType = {....};
> char c = getc();
> int type = characterType[c];
>
> Funktioniert mit 7 Bit Ascii einwandfrei. Ob es in Deutschland
> funktioniert, hängt davon ab, ob der Compiler char als signed oder
> unsigned behandelt.

Deshalb macht man das auch nicht so. Man muß es in C halt machen, wie in 
vielen anderen Sprachen auch: Wenn ich einen Zahlenwert haben will, muß 
ich eine geeignete Typkonvertierung machen. Der einzige Unterschied ist, 
daß man bei C (anders als z.B. in Pascal) auch direkt an den internen 
Wert der char-Variable kommt.
Moderator #4264710
Lesenswert?
• ▲
▼
So ein verdammter Murks schrieb:
> Der größte Murks, den jemals ein Amerikaner erfunden hat.
>
>  int[] characterType = {....};
>  char c = getc();
>  int type = characterType[ c];

Du meinst wahrscheinlich
1
  int characterType[] = {....};
2
  char c = getchar();
3
  int type = characterType[c];

getchar liefert ein int, als Array-Index wird ein size_t erwartet.
Deklariert man c als einen diese beiden Typen, funktioniert das Ganze
auch mit 8-Bit-Zeichencodierungen. char als Datentyp für c ist hier
aber völlig fehl am Platz.
#4264747
Lesenswert?
• ▲
▼
Yalu X. schrieb:
> getchar liefert ein int, als Array-Index wird ein size_t erwartet.

Wie ist dass zu verstehen? Meines wissens gibt es keine Vorgabe mit 
welchen arithmetischen Datentypen die Arraysubscription durchgeführt 
werden sollte. Es gillt sogar ""[0] ist equivalent zu *(""+0) und zu 
0[""]

> Deklariert man c als einen diese beiden Typen, funktioniert das Ganze
> auch mit 8-Bit-Zeichencodierungen.

Das trifft zu, aber ich finde Code sollte immer funktionieren, und nicht 
nur wenn gewisse Annahmen zutreffen. Ich würde c in diesem Beispiel als 
'unsigned int' definieren, da dieser Datentyp gleichgross ist wie ein 
int, aber nicht negativ sein kann, und mit sizeof prüfen ob etwas an dem 
Arrayindex steht:
1
  int characterType[] = {....};
2
  unsigned c = getchar();
3
  int type = 0;
4
  if( c < sizeof(characterType)/sizeof(*characterType) )
5
    type = characterType[c];

size_t gefällt mir hier nicht, weil der Wertebereich in keinem 
zusammenhang zu dem der Eingabedaten (ein int von getchar) steht.
#4264812
Lesenswert?
• ▲
▼
Yalu X. schrieb:

> getchar liefert ein int,

Schon richtig.
Aber der Hintergrund ist ein anderer.
getchar liefert prinzipiell schon einen char (promomted nach int), hat 
aber die Notwendigkeit auch EOF liefern zu können. Und damit ist der 
Wertebereich, den getchar liefern können muss um 1 über dem Wertebereich 
von char. Deshalb ist der Return Wert ein int.

> Deklariert man c als einen diese beiden Typen, funktioniert das Ganze
> auch mit 8-Bit-Zeichencodierungen.

Da EOF meistens als -1 codiert ist, gibt es dann allerdings Probleme, 
wenn das nicht vorher ausgefiltert wird.
Moderator #4265000
Lesenswert?
• ▲
▼
Daniel A. schrieb:
> Yalu X. schrieb:
>> getchar liefert ein int, als Array-Index wird ein size_t erwartet.
>
> Wie ist dass zu verstehen? Meines wissens gibt es keine Vorgabe mit
> welchen arithmetischen Datentypen die Arraysubscription durchgeführt
> werden sollte.

Ja, es gibt lediglich die Vorgabe, dass der Index "integer type" haben
muss. Damit ist von signed char bis zu long long int alles erlaubt.
Aber natürlich sollte der Wertebereich des verwendeten Typs groß genug
sein, um die gesamte Array-Größe abzudecken. Der Wertebereich eines
vorzeichenbehafteten char reicht aber üblicherweise nur bis 127. Mit
size_t ist man aber immer auf der sicheren Seite, da kein Array mehr
als size_t Elemente enthalten kann (sonst würde der sizeof-Operator
nicht mehr funktionieren).

Karl H. schrieb:
> Schon richtig.
> Aber der Hintergrund ist ein anderer.

Auf jeden Fall ist es in obigem Beispiel unsinnig, ein char zu nehmen,
da dieses dort weder als Array-Index taugt noch die Unterscheidung
zwischen dem Zeichen '\xff' und EOF erlaubt (wenn man eine entsprechende
Abfrage einbauen wollte).
Moderator Persönliche Seite #4265238
Lesenswert?
• ▲
▼
Marc D. schrieb:
> Koe schrieb:
>
>> unsigned char a_uchar_= '\0';
>> unsigned char a_uchar_= 0;
>
>> Bewirkt doch das selbe, oder nicht ?
>
> NEIN,
> das eine ist 0x00 oder auch bekannt als NULL,
> das andere ist 0x30 ASCII für die Zahl Null.

Beides leider falsch. Ersteres ist bekannt als NUL - mit einem L. Mit 
NULL, meist im Zusammenhang mit "Nullpointern" zu sehen, hat das 
überhaupt nichts zu tun.

Siehe auch:

   http://man7.org/linux/man-pages/man7/ascii.7.html

Das andere ist nicht 0x30 ASCII, denn dann hätte man es '0' (mit 
Hochkommata) schreiben müssen. Wurde es aber nicht. 0 ist 0 und nix 
anderes. Beide Zuweisungen ergeben denselben Code.
#4266376
Lesenswert?
• ▲
▼
Frank M. schrieb:
>> das eine ist 0x00 oder auch bekannt als NULL,
>> das andere ist 0x30 ASCII für die Zahl Null.
>
> Beides leider falsch. Ersteres ist bekannt als NUL - mit einem L. Mit
> NULL, meist im Zusammenhang mit "Nullpointern" zu sehen, hat das
> überhaupt nichts zu tun.

Das ist durchaus als Definition für NULL erlaubt:
1
#define NULL 0x00

Allerdings nutzt man NULL beser nur im Zeigerkontext.
Moderator Persönliche Seite #4266413
Lesenswert?
• ▲
▼
Rolf M. schrieb:
> Das ist durchaus als Definition für NULL erlaubt:
>
1
> #define NULL 0x00
2
>


Natürlich ist das als NULL erlaubt. Ist auch meistens genau so 
definiert, siehe <stdio.h>.

Aber das Zeichen '\0' heisst NUL (mit einem L), so wie

  '\a' BEL (bell)
  '\b' BS  (backspace)
  '\t' HT  (horizontal tab)
  '\n' NL  (newline)
  '\v' VT  (vertical tab)
  '\f' FF  (formfeed)
  '\r' CR  (carriage return)

heisst.

Also ausführlich:

  '\0' NUL (null character)

Und NUL (das Zeichen) hat nichts mit NULL (dem Nullpointer) zu tun. Dass 
beide Werte in den meisten C-Programmierumgebungen den numerischen Wert 
0 haben, ist purer Zufall - aber meist bequem für den Programmierer.

Deshalb sollte man, wenn man das Zeichen meint, auch '\0' schreiben, 
z.B.
1
  char *s;
2
  ...
3
  *(s + 5) = '\0';    // terminate string here!

Und wenn man den Nullpointer meint, dann das:
1
  FILE * fp;
2
  char * filename = "foo.bar";
3

4
  fp = fopen (filename, "r");
5

6
  if (fp == NULL)
7
  {
8
      perror (filename);
9
      ...
10
  }
11
  ...

Aber ich käme nie auf die Idee,
1
  *(s + 5) = NULL
oder
1
  if (fp == '\0')

zu schreiben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren