47 votes

Quelle est la particularité de R et L dans le préprocesseur C ++?

J'ai couru le code suivant par le biais de Visual Studio 2013 de préprocesseur. La sortie me surprend.

Contenu de hello.cpp:

#define A(j) #j

A(A?)
A(B?)
A(C?)
A(D?)
A(E?)
A(F?)
A(G?)
A(H?)
A(I?)
A(J?)
A(K?)
A(L?)
A(M?)
A(N?)
A(O?)
A(P?)
A(Q?)
A(R?)
A(S?)
A(T?)
A(U?)
A(V?)
A(W?)
A(X?)
A(Y?)
A(Z?)

La commande:

cl /P hello.cpp

bonjour.j'contient:

#line 1 "hello.cpp"



"A?"
"B?"
"C?"
"D?"
"E?"
"F?"
"G?"
"H?"
"I?"
"J?"
"K?"
"L"
"M?"
"N?"
"O?"
"P?"
"Q?"
"R"
"S?"
"T?"
"U?"
"V?"
"W?"
"X?"
"Y?"
"Z?"

J'ai couru dans le présent, tout en essayant d'appeler Un(L?p:q), ce qui a entraîné "Lp:q" qui n'est pas bon pour moi.

Est ce propre, bien défini C++? Ce qui est spécial au sujet de L et R en C++? Si le fichier a la .c extension, L et R sont traités à l'identique pour le reste de l'alphabet. Est-ce lié à C++11? Il doit être une nouvelle fonctionnalité, comme les anciennes versions de MSVS n'est pas de la bande de roulement L et R d'une manière spéciale.

Et que puis-je faire pour arrêter MSVS 2013 à partir de traitement de L et la R dans cette manière particulière?

20voto

Shafik Yaghmour Points 42198

Mise à jour

Ressemble le rapport de bug a été marquée comme un double de ce un qui a une mise à jour qui dit:

Un correctif de ce problème a été vérifié dans le compilateur sources. Le correctif devrait apparaître dans la prochaine version majeure de Visual C++.

D'origine

Comme remyabel souligné c'est un rapport de bogue. Ni gcc ni clang produire ce résultat et la stringizing opérateur # selon Visual Studios documents, ce sont les remplacements suivants (l'accent de la mine à l'avenir):

L'espace blanc qui précède le premier signe de l'argument réel et suivant le dernier jeton de la réelle argument est ignoré. Tout espace blanc entre les jetons dans le réel argument est réduite à un seul espace blanc de la chaîne littérale. Ainsi, si un commentaire se produit entre deux jetons dans l'argument réel, il est réduit à un seul espace blanc. La chaîne résultante littérale est automatiquement concaténé avec avoisinant les littéraux de chaîne à partir de laquelle il est séparé par un espace blanc.

En outre, si un personnage figurant dans l'argument nécessite généralement une séquence d'échappement lorsqu'utilisé dans une chaîne littérale (par exemple, les guillemets (") ou la barre oblique inverse ()), l'évasion nécessaire barre oblique inverse est automatiquement inséré avant le caractère.

ce qui correspond avec le C++ avant-projet de norme section 16.3.2 # opérateur qui dit:

Si, dans la liste de remplacement, un paramètre est immédiatement précédé d'un # prétraitement jeton, les deux sont remplacées par une seule chaîne de caractères littérale de prétraitement jeton contenant de l'orthographe d'un prétraitement jeton de la séquence correspondante argument. Chaque occurrence de l'espace blanc entre l'argument du prétraitement des jetons devient un espace unique de caractères dans la chaîne de caractères littérale. L'espace blanc avant le premier prétraitement jeton et après la dernière prétraitement jeton comprenant l'argument est supprimé. Sinon, l'orthographe d'origine de chaque prétraitement jeton dans l'argument est retenu dans la chaîne de caractères littérale, sauf pour un traitement spécial pour la production de l'orthographe de littéraux de chaîne et les chaînes de caractères: un caractère \ est insérée avant chaque "et \ caractère d'un personnage littéral ou un littéral de chaîne (y compris la délimitation des" caractères).

La seule chose qui se rapporte R et L à l'égard de C++11 , c'est qu'ils ont une signification spéciale avec des littéraux de chaîne , mais je ne vois pas comment il doit procéder à cette affaire.

Aussi, on dirait L\ et R\ produire le même problème.

Ils font un document non-conformité et il dit:

Visual C++ ne se comporte pas correctement lorsque le # (stringize) opérateur est utilisé avec des chaînes qui comprennent des séquences d'échappement. Dans ce cas, le compilateur va générer d'Erreur du Compilateur C2017.

qui ne couvre pas ce cas.

3voto

Rastaban Points 312

Cela semble être un bogue dans le préprocesseur MSVC. La bonne nouvelle est que vous pouvez contourner le problème en mettant un espace après le R ou le L.

 A(L ?p:q), // "L ?p:q"
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X