Napisałem ten kod, który tworzy identyfikatory zawierające uniwersalne nazwy postaci poprzez łączenie tokenów.Tworzenie identyfikatorów zawierających uniwersalne nazwy znaków poprzez łączenie tokena
//#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;
}
Ten kod działa dobrze z gcc 4.8.2 with -fextended-identifiers
option i gcc 5.3.1, ale nie działa z clang 3.3 z komunikatem o błędzie:
prog.c:10:17: error: use of undeclared identifier 'ねこ'
printf("%d\n", \u306d\u3053);
^
1 error generated.
i lokalnym dzyń (wersja 7.0.2 Jabłko LLVM (dzyń-700.1.81)) z komunikatem o błędzie:
$ 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.
Kiedy użyłem -E
opcję, aby kod wyjściowy kompilatory z makro rozszerzonym, gcc 5.3.1 emitowane t jego:
# 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;
}
lokalny dzyń emitowany to:
# 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;
}
Jak widać, identyfikatory zadeklarowane i stosowane w printf()
meczów w wyjście GCC, ale nie są one zgodne z wyjściem dzyń za.
Wiem, że tworzenie uniwersalnych nazw znaków poprzez łączenie tokenów powoduje wywołanie niezdefiniowanego zachowania.
Cytat N1570 5.1.1.2 faz Tłumaczenie:
Jeżeli sekwencja znaków, które mecze składnię uniwersalnej nazwy znaków jest produkowany przez token konkatenacji (6.10.3.3), zachowanie jest niezdefiniowane.
myślałem, że ta sekwencja znaków \u306d\u3053
może „dopasować składni uniwersalnego charakteru nazwy” ponieważ zawiera uniwersalne imiona postaci jak jego fragmentu. Sądziłem również, że "dopasowanie" może oznaczać, że cały token wygenerowany przez konkatenację oznacza jedną uniwersalną nazwę postaci, i dlatego to niezdefiniowane zachowanie nie jest wywoływane w tym kodzie.
Reading PRE30-C. Do not create a universal character name through concatenation znalazłem komentarz mówiąc tego rodzaju konkatenacji jest dozwolone:
Co jest zabronione, aby utworzyć nowy UCN poprzez konkatenacji. Jak robi
Assign (\ u0001,0401, a, b, 4)
tylko łączenie rzeczy, które dzieje się zawierać UCNs wszędzie jest w porządku.
Dziennik, który pokazuje, że a code example like this case (but with 4 characters) został zastąpiony przez another code example.
Czy mój przykład kodu wywołuje niektóre niezdefiniowane zachowania (nie ograniczając się do tych wywoływanych przez tworzenie uniwersalnych nazw znaków poprzez łączenie tokenów)? A może to błąd w klangu?
Jeśli chodzi o mnie, gcc 5.3.1 wygląda o wiele gorzej ... odkomentuj '// printf ("% d \ n ", CAT (\ u306d, \ u3053)); narzeka. Z brzękiem uzyskuję co najmniej spójne wyniki - mogę odkomentować wszystkie linie i zaakceptować je, ponieważ wynik użycia "CAT" konsekwentnie różni się od bezpośredniego konkatenacji. – grek40
@ grek40 gcc 6.1 nie narzeka na to, wydaje się ale w gcc 5.3.1 (nie wypróbowany)? – user1887915
trigrafów, digrafów, UCN ... po prostu powiedz NIE. – chqrlie