Forum: Compiler & IDEs AVR-GCC: Welcher Zeichensatz?


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich habe den Forenbeitrag ähnlichen Namens anno 2011 durchaus gefunden- 
dort wird die Frage aber nicht geklärt, sondern ein anders liegender 
Fehler gefunden.

Welchen Zeichensatz nutzt eigentlich AVR-GCC? Konkret ist im Quelltext 
unter AtmelStudio 6 ein "µ"-Zeichen als Integer "181" vom ATmega 
angezeigt worden. Nach:

http://en.wikipedia.org/wiki/Mu_(letter)

könnte das Unicoder oder UTF-8 sein. Auf den ersten Blick klingt beides 
für den kleinen AVR unglaubwürdig. Oder nutzt AVR-GCC einfach den 
Zeichensatz des Quellsystems (bei mir Windows 7), d.h. der Source-Code 
würde auf einem Linux-System anders kompiliert, wenn ich das Zeichen 
über die Tastatur eingebe und eine direkte Eingabe des Sonderzeichen als 
Escape-Sequenz mit Hex-Code des Zeichens wäre ratsam?

Viele Grüße
Nicolas

von Peter II (Gast)


Lesenswert?

der Zeichensatz spielt doch überhaupt keine rolle.

Das zeichen µ (181) wird einfach als 181 weiter verwendet. Wenn du es 
per Print ausgibtst dann kommt halt wieder eine 181 raus.

von Oliver (Gast)


Lesenswert?

Nicolas S. schrieb:
> Konkret habe ist im
> Quelltext unter AtmelStudio 6 ein "µ"-Zeichen als Integer "181" vom
> ATmega angezeigt worden.

Wie zeigt deín Prozessor etwas an? Hast du einen ATMega mit eingebautem 
Display?

Oliver

von Walter T. (nicolas)


Lesenswert?

Natürlich spielt der Zeichensatz eine Rolle. Wenn ich im Quelltext ein 
char mit dem Inhalt 'µ' erzeuge, ist es durchaus von Bedeutung, welchen 
Zahlenwert der Kompiler daraus macht - schließlich muß ich meinen 
Zeichensatz danach auslegen.

Eingebaut ist das Display nicht, aber angehängt. Und einen char kann ich 
ja durchaus als int anzeigen. Muß ich sogar, wenn ich den Zeichensatz 
entwerfe.

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> Natürlich spielt der Zeichensatz eine Rolle. Wenn ich im Quelltext ein
> char mit dem Inhalt 'µ' erzeuge, ist es durchaus von Bedeutung, welchen
> Zahlenwert der Kompiler daraus macht - schließlich muß ich meinen
> Zeichensatz danach auslegen.

nein macht es nicht. Er nimmt es so wie es kommt und wenn die es 
ausgibtst bekommst du es genauso zurück.

Das ist wie ein Tonbandgerät, dem ist auch die Sprache egal.

Der eigentliche Quellcode ist ASCII. Was in "Strings" steht spielt keine 
rolle.

von Walter T. (nicolas)


Lesenswert?

Peter II schrieb:
> Der eigentliche Quellcode ist ASCII. Was in "Strings" steht spielt keine
> rolle.

Die DOS-Erweiterung von ASCII ist es schonmal nicht. Da steht "mu" an 
Stelle 230 und an Stelle 181 ist ein Stück Rahmen.

Peter II schrieb:
> Das ist wie ein Tonbandgerät, dem ist auch die Sprache egal.

Der kleine AVR ist auch kein Tonbandgerät. Tonbandgeräte kenne ich noch. 
Die haben keinen Zeichensatz. Die haben nur <<  ■ || > >>, und das auch 
nur aufgedruckt.

Und wenn ich an einem Display einen Zeichensatz habe, der vom AVR 
erzeugt wird, ist es durchaus von Wichtigkeit, welches Zeichen im 
Quelltext zu welcher Zahl im char führen, ansonsten müßte ich nämlich 
jeden Text als Array eingeben. Will ich aber nicht. Mache ich über die 
Tastatur. Nur bei Sonderzeichen ist es interessant, ob das erzeugte 
Zeichen für jede Erzeugerplattform gleich ist. Ansonsten ist der 
Quelltext nicht portabel.

Deswegen ist für mich die Kenntnis des von AVR-GCC genutzten 
Zeichensatzes DOCH interessant. Ich finde es auch nicht schlimm, wenn 
andere das langweilig finden. Ich aber nicht.

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> Peter II schrieb:
>> Der eigentliche Quellcode ist ASCII. Was in "Strings" steht spielt keine
>> rolle.
>
> Die DOS-Erweiterung von ASCII ist es schonmal nicht. Da steht "mu" an
> Stelle 230 und an Stelle 181 ist ein Stück Rahmen.

der µ steht aber nicht als code sondern als String und dort spielt der 
zeichensatz keine rolle. (er spielt auch im code keine Rolle, nur 
mekkert der compiler wenn du versucht eine Variabel mit nicht ASCCI 
zeichen anzulegen)

> Und wenn ich an einem Display einen Zeichensatz habe, der vom AVR
> erzeugt wird, ist es durchaus von Wichtigkeit, welches Zeichen im
> Quelltext zu welcher Zahl im char führen, ansonsten müßte ich nämlich
> jeden Text als Array eingeben. Will ich aber nicht.
Dabei hilft dir der zeichensatz nicht weiter. Der compieler macht 
überhaupt keine änderung von zeichen oder Berücksichtigt einen 
Zeichensatz.

Wenn dein Display eine 230 für ein zeichen will, dann musst du im 
Quelltext eine 230 hinschreiben egal wie das zeichen das aussieht.


Der Compieler ändere keine Zeichen, also spielt er Zeichensatz keine 
Rolle!

von Stefan E. (sternst)


Lesenswert?

Nicolas S. schrieb:
> Deswegen ist für mich die Kenntnis des von AVR-GCC genutzten
> Zeichensatzes DOCH interessant.

Nein, der avr-gcc nimmst wie es kommt.
Was dich interessiert, ist, welchen Zeichensatz dein Editor verwendet. 
Und das lässt sich für gewöhnlich einstellen.

von Oliver (Gast)


Lesenswert?

Der (avr-)gcc nutzt überhaupt keinen Zeichensatz. Der bekommt ein 
Source-File vorgesetzt, in dem er eine char-Konstante mit dem 
Integer-Wert 181 vorfindet. Welches Zeichen das ist, ist dem Compiler 
herzlich egal. Der übernimmt diese 181 einfach ins Hex-File.

Die Umwandlung des auf deinem Rechener-Bildschirm sichtbaren "µ" in des 
Char -Wert 181 macht nicht der Compiler, sondern der Editor. Und welchen 
Zeichensatz der benutzt, ist tatsächlich abhängig vom Betriebssystem, 
aber auch vom Editorprogramm selber.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Als C-Programmierer solltest du dir angewöhnen, dass du dich auf den 
originalen ASCII-Zeichensatz berufen darfst. 7-Bit - Kleinbuchstaben, 
Großbuchstaben, Ziffern und ein paar Sonderzeichen.
Alles darüber hinausgehende, insbesondere was bei gesetztem 8. Bit 
rauskommt, ist eine Frage von Gottvertrauen, Editor und hängt nicht 
zuletzt auch davon ab, was dein Ausgabegerät mit diesen Bytes macht.

von Walter T. (nicolas)


Lesenswert?

OK, das heißt also, daß ich mich nicht darauf verlassen kann, daß der 
AVR-GCC auf jedem Rechner den gleichen Zeichensatz nutzt. (Oder 
präziser: Die Eingaben der Textdatei außerhalb des kleinen 
ASCII-Zeichensatzes gleich interpretiert).

Dann bleibt für die Eingabe von Sonderzeichen also nur die Nutzung von 
Escapesequenzen mit dem Zeichen im Oktalcode. Kann ich mit leben. 
Tastatur wäre mir lieber gewesen. Hex wäre mir auch lieber gewesen. So 
sinkt eben stufenweise die Lesbarkeit - wenn's nicht besser geht, geht 
es nicht besser. Aber ob das wirklich nötig ist, wollte ich vorher 
geklärt wissen.

Danke für die Antworten
Nicolas

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> OK, das heißt also, daß ich mich nicht darauf verlassen kann, daß der
> AVR-GCC auf jedem Rechner den gleichen Zeichensatz nutzt. (Oder
> präziser: Die Eingaben der Textdatei außerhalb des kleinen
> ASCII-Zeichensatzes gleich interpretiert).

immer nocht nicht verstanden! Der GCC nutzt keine Zeichensatz, er macht 
auch auf jeden System das gleiche. Nur wie dein Editor die Quelltext 
anzeigt kann anders sein.

> Dann bleibt für die Eingabe von Sonderzeichen also nur die Nutzung von
> Escapesequenzen mit dem Zeichen im Oktalcode. Kann ich mit leben.
> Tastatur wäre mir lieber gewesen. Hex wäre mir auch lieber gewesen.

wo soll jetzt der unteschied zwischen Hex und Oktalcode sein?

von Karl H. (kbuchegg)


Lesenswert?

Nicolas S. schrieb:
> OK, das heißt also, daß ich mich nicht darauf verlassen kann, daß der
> AVR-GCC auf jedem Rechner den gleichen Zeichensatz nutzt.

Das ganze hat nichts mit dem gcc zu tun!


Ein Compiler ist ein Programm welches eine Eingabedatei 'verwurschtet'. 
Welche Zeichen-Codes auch immer der Editor dort abgelegt hat, die werden 
vom Compiler benutzt.

Kann es sein, dass du noch nicht gemerkt hast, dass dein C-Programm, so 
wie du es mit dem Editor schreibst, auch nichts anderes als eine Abfolge 
von Code-Bytes ist? Dein Editor ist so freundlich und schreibt dir 
anstelle der Code Bytes, die zugehörigen Zeichen auf den Bildschirm. 
Aber Code ist Code. Eine C-Datei (oder überhaupt eine Text-Datei)
1
int main()
2
{
3
  return 0;
4
}
ist auf Dateiebene auch nichts anderes als eine Abfolge von ASCII Codes.

Der Compiler liest dieses und was auch immer an Codes in einem String 
vorkommt, das schreibt er so wie es ist, dann auch ins Programm hinein.

> Dann bleibt für die Eingabe von Sonderzeichen also nur die Nutzung von
> Escapesequenzen mit dem Zeichen im Oktalcode. Kann ich mit leben.

Kann man sich organisieren. Zb. Mit Präprozessorhilfe und der Regel, 
dass der Compiler aufeinanderfolgende String-Literale zu einem einzigen 
Literal zusammenfassen muss.

von Walter T. (nicolas)


Lesenswert?

Peter II schrieb:
> wo soll jetzt der unteschied zwischen Hex und Oktalcode sein?

Ganz einfach:
1
fprintf("\265C.net"); // geht
2
fprintf("\xb5C.net"); // geht nicht.

von Norbert (Gast)


Lesenswert?

Bei mir nutzt der arm-gcc den Zeichensatz welcher der Shell Einstellung 
entspricht. Ich vermute der avr-gcc macht's nicht anders.
1
$ export LANG=de_DE.UTF-8
2
$ vi x.c
3
void main(void)
4
{
5
    char x[] = {"ABCµXYZ"};
6
}
7
$ /opt/gcc-arm-none-eabi-4_7-2013q1/bin/arm-none-eabi-gcc -c x.c
8
$ hexdump -C x.o |grep ABC
9
00000060  00 00 00 00 41 42 43 c2  b5 58 59 5a 00 00 00 00  |....ABC..XYZ....|
10
11
12
13
14
$ export LANG=C
15
$ vi x.c
16
void main(void)
17
{
18
    char x[] = {"ABCµXYZ"};
19
}
20
$ /opt/gcc-arm-none-eabi-4_7-2013q1/bin/arm-none-eabi-gcc -c x.c
21
$ hexdump -C x.o |grep ABC
22
00000060  41 42 43 b5 58 59 5a 00  00 47 43 43 3a 20 28 47  |ABC.XYZ..GCC: (G|

von Stefan E. (sternst)


Lesenswert?

Norbert schrieb:
> Bei mir nutzt der arm-gcc den Zeichensatz welcher der Shell Einstellung
> entspricht.

Nein!
Der vi ist in deinem Beispiel derjenige, der einen Zeichensatz benutzt 
und für die Unterschiede verantwortlich ist.

von Peter II (Gast)


Lesenswert?

Norbert schrieb:
> Bei mir nutzt der arm-gcc den Zeichensatz welcher der Shell Einstellung
> entspricht. Ich vermute der avr-gcc macht's nicht anders.

macht er nicht. Der VI nutzt den zeichensatz nicht der GCC.

Nicolas S. schrieb:
> Ganz einfach:
> fprintf("\265C.net"); // geht
> fprintf("\xb5C.net"); // geht nicht.


oktal muss mit 0 einfangen!

von Norbert (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Norbert schrieb:
>> Bei mir nutzt der arm-gcc den Zeichensatz welcher der Shell Einstellung
>> entspricht.
>
> Nein!
> Der vi ist in deinem Beispiel derjenige, der einen Zeichensatz benutzt
> und für die Unterschiede verantwortlich ist.

Jo, war unklar ausgedrückt!
Ich wollte zum Ausdruck bringen, das wenn ich mich in einem UTF8 
Environment befinde, man zB kein µ in eine char Variable packen kann.

Da gibt's dann so etwas:
warning: multi-character character constant [-Wmultichar]

Aber du hast Recht, letztlich wird ein 'µ' je nach Env. verschieden im 
Sourcecode hinterlegt.

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> fprintf("\265C.net"); // geht
> fprintf("\xb5C.net"); // geht nicht.

nachtrag:

http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0035.htm

von Stefan E. (sternst)


Lesenswert?

Peter II schrieb:
> Nicolas S. schrieb:
>> Ganz einfach:
>> fprintf("\265C.net"); // geht
>> fprintf("\xb5C.net"); // geht nicht.
>
>
> oktal muss mit 0 einfangen!

Nein. Ein Octal-Code in einem String ist ein Backslash mit drei Ziffern 
dahinter. \265 ist völlig korrekt.

von Karl H. (kbuchegg)


Lesenswert?

Nicolas S. schrieb:

> Ganz einfach:
>
1
> fprintf("\265C.net"); // geht
2
> fprintf("\xb5C.net"); // geht nicht.
3
>


Und wenn man es so schreibt
1
#define MUE "\xB5"
2
3
4
...
5
6
  fprintf( MUE"C.net" );

dann kann man das dann (meistens) sogar lesen und alle µ auf einem 
anderen LCD gegen die dort gültigen Codes an einer einzigen Stelle 
zentral austauschen.

von Peter II (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Nein. Ein Octal-Code in einem String ist ein Backslash mit drei Ziffern
> dahinter. \265 ist völlig korrekt.

oh stimmt, bei 3 stellen kann man es so schreiben. Aber dann sollte auch 
hex genauso gehen.

> fprintf("\xb5C.net"); // geht nicht.

gcc liefert auch:

 warning: hex escape sequence out of range [enabled by default]

scheint mir irgendwie ein Bug zu sein. Denn

fprintf("\xb5 C.net");

funktioniert. Er will scheinbar mehr als 2 zeichen HEX einlesen.

von Norbert (Gast)


Lesenswert?

Peter II schrieb:
> Stefan Ernst schrieb:
>> Nein. Ein Octal-Code in einem String ist ein Backslash mit drei Ziffern
>> dahinter. \265 ist völlig korrekt.
>
> oh stimmt, bei 3 stellen kann man es so schreiben. Aber dann sollte auch
> hex genauso gehen.
>
>> fprintf("\xb5C.net"); // geht nicht.
>
> gcc liefert auch:
>
>  warning: hex escape sequence out of range [enabled by default]
>
> scheint mir irgendwie ein Bug zu sein. Denn

Hängt damit zusammen das das 'C' noch als Teil des Hex Wertes angesehen 
wird.

Early termination funktioniert.

void main(void)
{
    char y[] = "\265C.net";
    char z[] = "\xb5""C.net";
}

von Walter T. (nicolas)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Kann es sein, dass du noch nicht gemerkt hast, dass dein C-Programm, so
> wie du es mit dem Editor schreibst, auch nichts anderes als eine Abfolge
> von Code-Bytes ist? Dein Editor ist so freundlich und schreibt dir
> anstelle der Code Bytes, die zugehörigen Zeichen auf den Bildschirm.
> Aber Code ist Code. Eine C-Datei (oder überhaupt eine Text-Datei)int
> main()
> {
>   return 0;
> }
> ist auf Dateiebene auch nichts anderes als eine Abfolge von ASCII Codes.

Nein, unter dem Blickwinkel habe ich es noch nie betrachtet. Für mich 
wurde aus einem Binärwurst immer erst durch einen definierten 
Zeichensatz ein lesbarer Text. Also war ich bislang davon ausgegangen, 
daß ein Compiler/Präprozessor sich die Sachen erstmal wieder in eine 
Textebene legt, allein um Leerzeichen, Tabs und Zeilenumbrüche zu 
interpretieren. Kompilerbau hatten wir im Maschinenbaustudium nicht.

Sollte es heute abend nicht zu heiß zum nachdenken sein, lasse ich mir 
den Wurm, der sich durch binärzeugs frißt, und dabei binärkode zu 
erzeugt, nochmal in Ruhe durch den Kopf gehen.

von Peter II (Gast)


Lesenswert?

Norbert schrieb:
> Hängt damit zusammen das das 'C' noch als Teil des Hex Wertes angesehen
> wird.

richtig, aber er sollte eigentlich nur 2 zeichen nach dem \x einlesen.

von Norbert (Gast)


Lesenswert?

Peter II schrieb:
> Norbert schrieb:
>> Hängt damit zusammen das das 'C' noch als Teil des Hex Wertes angesehen
>> wird.
>
> richtig, aber er sollte eigentlich nur 2 zeichen nach dem \x einlesen.

Ich meine gelesen zu haben, das bei '\x...' alles bis zum ersten 
'nichtHex' Zeichen beachtet wird.
Bei Oktal ist es auf drei Ziffern begrenzt.

von Walter T. (nicolas)


Lesenswert?

Karl Heinz Buchegger schrieb:
> fprintf( MUE"C.net" );

Das ist schön und lesbar.

Peter II schrieb:
> fprintf("\xb5 C.net");

Das erzeugt bei mir ein Leerzeichen zwischen µ und C.

Norbert schrieb:
> char z[] = "\xb5""C.net"

Das probiere ich heute abend auch mal. Hex kriege ich irgendwie besser 
in den Kopf als Oktal.

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> Also war ich bislang davon ausgegangen,
> daß ein Compiler/Präprozessor sich die Sachen erstmal wieder in eine
> Textebene legt, allein um Leerzeichen, Tabs und Zeilenumbrüche zu
> interpretieren.

das braucht er keinen zeichensatz weile diese zeichen im ASCII 
feststehen. Er kann also einfach den den byte-wert vergleichen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Um zum Kern der Frage zurückzukommen:

AVR-Studio verwendet als Unterbau das "Microsoft Visual Studio", das 
wiederum verwendet im Editor üblicherweise die sogenannte 
"ANSI"-Codepage (CP1252) - die ist weitestgehend identisch mit ISO 
8859-1*. Das ist bei praktisch allen unter Windows arbeitenden 
Editoren der Standardfall. Neuere Visual-Studio-Varianten (und auch 
der windowseigene Primitiveditor Notepad) unterstützen jedoch auch 
UTF-8.

Die alten "DOS"-Codepages CP437 bzw. CP850 werden zur allgemeinen 
Verwirrung aber weiterhin verwendet - in Konsolenfenstern.

Das lässt sich umschalten (mode con cp select=1252), bringt aber nur 
dann befriedigende Ergebnisse, wenn das Konsolfenster nicht mit dem 
defaultmäßigen Pixelfont betrieben wird -- diese Relikt aus der vorderen 
Altsteinzeit nämlich legt die Zeichencodierung zusätzlich fest.


Dem Compiler ist es weitestgehend wurscht, was er im Quelltext findet - 
alle Zeichencodierungen haben als Schnittmenge den ASCII-Zeichensatz, 
und alle für C oder C++ syntaktisch relevanten Zeichen befinden sich in 
diesem ASCII-Zeichensatz. Wenn in Kommentaren oder Stringkonstanten 
Zeichen auftauchen, die nicht im ASCII-Zeichensatz liegen (Umlaute 
etc.), dann kann der Compiler wahlweise Fehlermeldungen ausgeben, oder 
die im Quelltext vorgefundenen Zeichen so, wie sie sind, durchreichen.

Steht da also in einer Stringkonstante etwas, was im verwendeten 
Texteditor aussieht wie ein µ, dann landet das in exakt derselben Form 
auch im erzeugten Binärcode.

Ob der diesen dann abarbeitende Prozessor die Stringkonstante wiederum 
in lesbarer Form z.B. auf einem LC-Display ausgibt, hängt vom 
Zeichensatz des LC-Displays ab -- da beispielsweise HD44780-Displays 
keine CP1252 verwenden, funktioniert das mit solchen Displays nicht, 
und eine Umsetzungstabelle ist vonnöten.


*) http://de.wikipedia.org/wiki/ISO_8859-1

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Endlich mal ne gescheite Antwort nach all dem Halbwissen. Danke.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.