2009-07-30 6 views
5

Je vais avoir une macro comme ça (pas exactement, mais la fonction est tout à fait équivalent):différences dans l'opérateur Macro ## de concaténation entre Visual C++ et gcc

#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value 
... 
STRUCTMEMBER(Item,1); 

Cela fonctionne parfaitement dans Visual C++, mais gcc 3.4.5 (MingGW) donné l'erreur suivante:

pasting "." and "Item" does not give a valid preprocessing token

Cela se produit également lorsque j'utilise l'opérateur "->". Je n'ai pas trouvé d'indices sur la concaténation, que l'utilisation de ces opérateurs est interdite.

Est-ce que quelqu'un a une idée?

+1

http://gcc.gnu.org/ml/gcc-help/2003-04/msg00213.html tout usage? – AakashM

+0

Les espaces intentionnels? – EFraim

+0

Eh bien, j'ai lu les docs gcc et donc ils ont expliqué le ## en supprimant tous les espaces, donc je les ai juste mis pour la lisibilité. Ma première version n'avait pas d'espaces ... –

Répondre

7

Peut-être que Visual C++ colle deux espaces ensemble pour créer un autre espace. Ce n'est pas que les espaces sont des jetons, mais cela permettrait à votre code de fonctionner.

object.member n'est pas un jeton, il s'agit de trois jetons, vous n'avez donc pas besoin de copier-coller pour implémenter la macro que vous décrivez. Supprimez simplement le '##' et cela devrait fonctionner partout. [Edit: juste vérifié, et le résultat de l'utilisation de ## pour former quelque chose qui n'est pas un jeton valide est indéfini. Alors GCC est autorisé à rejeter et MSVC est autorisé à l'ignorer et ne pas effectuer la pâte, pour autant que je peux dire]

+0

Merci, je ne sais pas pourquoi, mais quand je l'ai essayé d'abord de cette façon, ça n'a pas marché ... à cause de cela, j'ai essayé l'opérateur ## .. Ça a l'air bien mieux maintenant! –

4

De l'gcc c preprocessor docs.

However, two tokens that don't together form a valid token cannot be pasted together.

structure.member est pas un seul jeton .

Dans ce cas, vous n'avez pas besoin d'utiliser l'opérateur ## (concaténation de jetons). Vous pouvez simplement l'enlever. Voici un exemple testé avec gcc sur linux 4.2.4:

#include <stdio.h> 

#define STRUCTMEMBER(Member, Value) GlobalStructInstance.Member = Value 

struct { 
    const char* member1; 
}GlobalStructInstance; 

int main(void) 
{ 

    STRUCTMEMBER(member1, "Hello!"); 

    printf("GlobalStructInstance.member1 = %s\n", 
      GlobalStructInstance.member1); 

    return 0; 
} 
5

Selon la norme C, le résultat de l'opérateur de pré-traitement « ## » doit être un « prétraiter jeton » ou le résultat est indéfini (C99 6.10 .3.3 (3) - L'opérateur ##).

La liste des jetons de pré-traitement est (C99 6.4 (3) - éléments lexicaux):

header names, identifiers, preprocessing numbers, character constants, string literals, punctuators, and single non-white-space characters that do not lexically match the other preprocessing token categories.

GCC vous permet de savoir que vous êtes entrée sur le territoire non défini. MSVC est silencieuse avec le résultat indéfini (c'est ce que vous attendez à peu près).

Notez que si vous ne créez pas un seul jeton de toute façon, vous n'avez pas besoin de l'opérateur de collage de jetons. Généralement (je suis sûr qu'il y a probablement une exception ou deux), 2 jetons séparés par des espaces sont équivalents à 2 jetons non séparés par des espaces - comme dans votre exemple.

Questions connexes