72 votes

MSVC ne développe pas __VA_ARGS__ correctement

Considérez ce code :

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)

Le résultat attendu est X = 1 and VA_ARGS = 2, 3 pour les deux macros, et c'est ce que j'obtiens avec GCC, cependant, MSVC développe ceci comme :

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =

C'est-à-dire, __VA_ARGS__ est développé en un seul argument, au lieu d'être décomposé en plusieurs.

Y a-t-il un moyen de contourner ce problème ?

73voto

Ise Wisteria Points 5852

Modifier : Ce problème peut être résolu en utilisant /Zc:preprocessor o /experimental:preprocessor dans les MSVC récents. Pour plus de détails, veuillez consulter aquí .

Le préprocesseur de MSVC semble se comporter de manière assez différente de la norme standard.
La solution de contournement suivante vous aidera probablement :

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )

0 votes

__VA_ARGS__ ne fait pas encore partie du standard C++. Le projet de norme spécifie-t-il réellement le comportement à adopter dans ce cas ?

1 votes

@bk1e : Désolé, comme je n'en ai pas la capacité, je ne peux pas expliquer ici en détail le prétraitement dans la norme C++ à venir, mais il est peu probable qu'il soit très différent de C99.

2 votes

Quelqu'un pourrait-il expliquer cela ? Est-ce que "et VA_ARGS = VA_ARGS Si c'est du code valide, qu'est-ce que "et VA_ARGS =", ou est-ce un texte lisible par l'homme qui est ici comme un commentaire ? VA_ARGS "en train de faire ? Merci.

32voto

dmitryvolk Points 281

J'ai posté le problème d'assistance Microsoft suivant :

Le programme suivant donne une erreur de compilation car le précompilateur développe __VA_ARGS__ incorrectement :

#include <stdio.h>

#define A2(a1, a2) ((a1)+(a2))

#define A_VA(...) A2(__VA_ARGS__)

int main(int argc, char *argv[])
{
    printf("%d\n", A_VA(1, 2));
    return 0;
}

Le préprocesseur étend le printf à : printf("%d \n ", ((1, 2)+())) ;

au lieu de printf("%d \n ", ((1)+(2))) ;

J'ai reçu la réponse insatisfaisante suivante de la part d'un développeur de l'équipe de compilateurs de Microsoft :

Bonjour : Le compilateur Visual C++ se comporte correctement dans ce cas. Si vous combinez la règle selon laquelle les tokens qui correspondent au '...' lors de l'invocation initiale de la macro sont combinés pour former une seule entité (16.3/p12) avec la règle selon laquelle les sous-macros sont développées avant le remplacement des arguments (16.3.1/p1), le compilateur pense dans ce cas que A2 est invoqué avec un seul argument : d'où le message d'erreur.

0voto

chys Points 682

Quelle version de MSVC utilisez-vous ? Vous aurez besoin de Visual C++ 2010.

__VA_ARGS__ a été introduit pour la première fois par C99. MSVC n'a jamais essayé de supporter C99, donc le support n'a pas été ajouté.

Maintenant, cependant, __VA_ARGS__ est inclus dans la nouvelle norme C++, C++2011 (anciennement connue sous le nom de C++0x), que Microsoft prévoit apparemment de prendre en charge, de sorte qu'il a été pris en charge dans les versions récentes de MSVC.

BTW, vous devrez utiliser un .cpp à votre fichier source pour obtenir ce support. MSVC n'a pas mis à jour son frontal C depuis longtemps.

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