Diferenças em macro operador ## concatenação entre o Visual C ++ e gcc
-
05-07-2019 - |
Pergunta
Eu estou tendo um macro assim (não exatamente, mas a função é bastante equivalente):
#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);
Isso funciona perfeitamente no Visual C ++, mas gcc 3.4.5 (MingGW) deu o seguinte erro:
colando "" e "Item" não dá uma pré-processamento válido símbolo
Isso também acontece quando eu uso o "->" operador. Eu não encontrei dicas sobre concatenação, que o uso destes operadores é proibido.
Alguém tem uma idéia?
Solução
Talvez Visual C ++ está colando um par de espaços em conjunto para fazer um outro espaço. Não que espaços em branco são símbolos, mas permitiria o seu código para o trabalho.
object.member
não é um símbolo, é três fichas, para que você não precisa token-colar para implementar a macro que você descreve. Basta remover o '##' e ele deve funcionar em todos os lugares.
[Edit: apenas marcada, eo resultado do uso de ## para formar algo que não é um token válido é indefinido. Então GCC é permitido para rejeitá-la e MSVC é permitido ignorá-la e executar sem cola, tanto quanto eu posso dizer.]
Outras dicas
De acordo com o padrão C, o resultado do '##
' pré-processamento operador deve ser um 'token de pré-processamento' ou o resultado é indefinido. (C99 6.10.3.3 (3) - O operador ##)
A lista de símbolos pré-processamento é (6,4 C99 (3) - elementos lexicais):
nomes de cabeçalho, identi fi ers, pré-processamento de números, constantes de caracteres, strings literais, pontuadores, e caracteres não-espaço em branco único que não lexically coincidir com o outro pré-processamento categorias simbólicas.
GCC permite que você saiba que você está entrando em território indefinido. MSVC é silenciosamente feliz com o resultado indefinido (que é o que seria praticamente esperar que aconteça).
Note que se você não está criando uma única qualquer maneira simbólica, então você não precisa o operador colando token. Geralmente (eu tenho certeza que há provavelmente uma exceção ou dois), 2 tokens separados por espaços em branco é equivalente a 2 fichas não separados por espaços em branco -. Como no seu exemplo
A partir da gcc c pré-processador docs :
No entanto, dois emblemas que não juntos formam um token válido não pode ser colado em conjunto.
structure.member não é um único token.
Neste caso, você não precisa usar o operador ## (concatenação token). Você pode simplesmente removê-lo. Aqui está um exemplo testado com gcc 4.2.4 no 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;
}