2009-07-30 7 views
5

estoy teniendo una macro como esta (no exactamente, pero la función es bastante equivalente):Las diferencias en Macro operador ## concatenación entre Visual C++ y gcc

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

Esto funciona perfectamente en Visual C++, pero gcc 3.4.5 (MingGW) dió el siguiente error:

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

Esto también sucede cuando se utiliza la "->" operador. No encontré pistas sobre la concatenación, que el uso de estos operadores está prohibido.

¿Alguien tiene una idea?

+1

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

+0

Los espacios intencionales? – EFraim

+0

bueno, he leído los documentos de gcc y, por lo tanto, me explicaron el ## eliminando todos los espacios, así que simplemente los coloqué para que sean legibles. Mi primera versión no tenía espacios ... –

Respuesta

7

Quizás Visual C++ está pegando un par de espacios juntos para hacer otro espacio. No es que los espacios en blanco sean tokens, sino que permitirían que tu código funcione.

object.member no es un token, son tres tokens, por lo que no necesita token-pegar para implementar la macro que describe. Simplemente elimina el '##' y debería funcionar en todas partes.

[Editar: acaba de marcar, y el resultado de usar ## para formar algo que no es un token válido no está definido. Así GCC se permite a rechazarlo y MSVC se permite ignorarlo y llevar a cabo no sólo pasta, por lo que yo puedo decir]

+0

Gracias, no sé por qué, pero cuando lo he intentado primero de esta manera no funcionó ... por eso probé el operador ## .. ¡se ve bastante mejor ahora! –

4

Desde el gcc c preprocessor docs:. Structure.member

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

no es un único token .

En este caso no necesita usar el operador ## (concatenación de token). Puedes simplemente eliminarlo. Aquí se prueba un ejemplo con gcc 4.2.4 en Linux:

#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

según el estándar C, el resultado de la '##' operador preprocesamiento debe ser un 'preprocesamiento contador' o el resultado es indefinido (C99 6,10 .3.3 (3) - El operador ##).

La lista de fichas de pre-procesamiento es (C99 6.4 (3) - elementos léxicos):

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 le permite saber que usted está entrando en territorio definido. MSVC está silenciosamente satisfecho con el resultado indefinido (eso es lo que esperarías que sucediera).

Tenga en cuenta que si no está creando un solo token de todos modos, entonces no necesita el operador de pegado del token. Generalmente (estoy seguro de que probablemente haya una o dos excepciones), 2 tokens separados por espacios en blanco son equivalentes a 2 tokens no separados por espacios en blanco, como en su ejemplo.

Cuestiones relacionadas