Ich habe diesen Code geschrieben, der Bezeichner erstellt, die universelle Zeichennamen über Token-Verkettung enthalten.
//#include <stdio.h>
int printf(const char*, ...);
#define CAT(a, b) a ## b
int main(void) {
//int \u306d\u3053 = 10;
int CAT(\u306d, \u3053) = 10;
printf("%d\n", \u306d\u3053);
//printf("%d\n", CAT(\u306d, \u3053));
return 0;
}
Dieser Code funktionierte gut mit gcc 4.8.2 mit -fextended-identifiers
Möglichkeit und gcc 5.3.1funktionierte aber nicht mit klingen 3.3 mit Fehlermeldung:
prog.c:10:17: error: use of undeclared identifier 'ねこ'
printf("%d\n", \u306d\u3053);
^
1 error generated.
und lokaler Clang (Apple LLVM Version 7.0.2 (clang-700.1.81)) mit Fehlermeldung:
$ clang -std=c11 -Wall -Wextra -o uctest1 uctest1.c
warning: format specifies type 'int' but the argument has type
'<dependent type>' [-Wformat]
uctest1.c:10:17: error: use of undeclared identifier 'ねこ'
printf("%d\n", \u306d\u3053);
^
1 warning and 1 error generated.
Als ich benutzte -E
Option, den Compiler-Ausgabecode mit Makro erweitert zu haben, gab gcc 5.3.1 Folgendes aus:
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
int printf(const char*, ...);
int main(void) {
int \U0000306d\U00003053 = 10;
printf("%d\n", \U0000306d\U00003053);
return 0;
}
local clang hat folgendes ausgegeben:
# 1 "uctest1.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 326 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "uctest1.c" 2
int printf(const char*, ...);
int main(void) {
int \u306d\u3053 = 10;
printf("%d\n", ねこ);
return 0;
}
Wie Sie sehen, sind die deklarierten und verwendeten Bezeichner in printf()
Übereinstimmungen in der Ausgabe von gcc, aber sie stimmen nicht mit der Ausgabe von clang überein.
Ich weiß, dass das Erstellen universeller Zeichennamen über Token-Verkettung undefiniertes Verhalten hervorruft.
Zitat aus N1570 5.1.1.2 Übersetzungsphasen:
Wenn durch Tokenverkettung (6.10.3.3) eine Zeichenfolge erzeugt wird, die der Syntax eines universellen Zeichennamens entspricht, ist das Verhalten undefiniert.
Ich dachte, dass diese Zeichenfolge \u306d\u3053
kann “mit der Syntax eines universellen Zeichennamens übereinstimmen”, da es universelle Zeichennamen als Teilzeichenfolge enthält. Ich dachte auch, dass “Match” bedeuten könnte, dass das gesamte durch Verkettung erzeugte Token für einen universellen Zeichennamen steht und dass dieses undefinierte Verhalten daher in diesem Code nicht aufgerufen wird.
Lektüre PRE30-C. Erstellen Sie keinen universellen Zeichennamen durch Verkettunghabe ich einen Kommentar gefunden, der besagt, dass diese Art der Verkettung erlaubt ist:
Was verboten ist, eine neue UCN per Verkettung zu erstellen. Wie tun
zuweisen(\u0001,0401,a,b,4)
Es ist in Ordnung, nur Dinge zu verketten, die zufällig irgendwo UCNs enthalten.
Und ein Protokoll, das das zeigt ein Codebeispiel wie in diesem Fall (aber mit 4 Zeichen) wird durch ersetzt noch ein Codebeispiel.
Ruft mein Codebeispiel einige undefinierte Verhaltensweisen auf (nicht beschränkt auf solche, die durch die Erzeugung universeller Zeichennamen über die Token-Verkettung aufgerufen werden)? Oder ist das ein Bug in Clang?
Soweit es mich betrifft, sieht der gcc 5.3.1 viel schlechter aus … kommentieren Sie das aus
//printf("%d\n", CAT(\u306d, \u3053));
Linie und es beschwert sich. Mit clang bekomme ich zumindest konsistente Ergebnisse – ich kann alle Zeilen auskommentieren und es akzeptiert es, da das Ergebnis von usingCAT
unterscheidet sich konsequent von der direkten Verkettung.– grek40
2. Mai 2016 um 17:05 Uhr
@grek40 gcc 6.1 beschwert sich nicht darüber, scheint ein aber in gcc 5.3.1 (nicht ausprobiert) ?
– Benutzer1887915
5. Mai 2016 um 4:46 Uhr
Trigraphen, Digraphen, UCN … sagen Sie einfach NEIN.
– chqrlie
5. Mai 2016 um 22:22 Uhr