Pergunta

Por que é que estes blocos de código produzir resultados diferentes?

Algum código:

#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)

caso 1:

#define GLUE(a,b,c) a##b##c  
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"

caso 2:

#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"

caso 3:

#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"

Eu estou usando MSVC++ a partir de VS.net 2005 sp1

Editar:atualmente, ele é a minha crença de que o pré-processador funciona assim durante a expansão de macros:Passo 1:- tomar o corpo - remove qualquer espaço em branco em torno ## operadores - analisar a cadeia, no caso em que um identificador é encontrado que coincide com o nome de um parâmetro:-se ele está ao lado de uma ## operador, substituir o identificador com o valor literal do parâmetro (por exemplo,a seqüência de caracteres passada) -se NÃO estiver ao lado de um ## operador, execute toda esta explicação processo sobre o valor do primeiro parâmetro e, em seguida, substituir o identificador com que resultado.(ignorando o stringafy único '#' caso atm) -remova todos os ## operadores

Passo 2:- assumir que a seqüência de caracteres resultante e analisá-lo para qualquer macros

agora, desde que eu acredito que todos os 3 casos, deve produzir exatamente a mesma seqüência de caracteres resultante:

PART1PART2*

e, portanto, após a etapa 2, deve resultar em

funciona*

mas pelo menos deve resultar na mesma coisa.

Foi útil?

Solução

casos 1 e 2 não têm nenhum comportamento definido desde o seu estão tentando colar um * em um pré-processamento do token.De acordo com as normas da associação do seu pré-processador isso tenta colar juntos os tokens PART1PART2 (ou apenas PART2) e *.No seu caso, isso provavelmente falhará silenciosamente, que é um dos resultados possíveis quando as coisas não estão bem definidos.O token PART1PART2 seguido por * não serão consideradas para expansão de macro novamente.Stringfication, em seguida, produz o resultado você vê.

Meu gcc se comporta de forma diferente em suas exemplos:

/usr/bin/gcc -O0 -g -std=c89 -pedantic   -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"

Então, para resumir o caso 1 tem dois problemas.

  • Colar dois tokens que não resultam válido de pré-processamento do token.
  • ordem de avaliação dos ## operador de

No caso 3, o seu compilador é dar o resultado errado.Ele deve

  1. avaliar os argumentos para STRINGAFY1
  2. para fazer o que ele tem para expandir GLUE
  3. GLUE resultados PART1PART2*
  4. o que deve ser expandido novamente
  5. o resultado é works*
  6. o que então é passado para STRINGAFY1

Outras dicas

Ele está fazendo exatamente o que você está dizendo a ele para fazer.A primeira e a segunda tirar os nomes de símbolo transmitido e colá-los juntos em um novo símbolo.A terceira leva de 2 símbolos e cola-los, então você está colocando o * na seqüência de si mesmo (o que, eventualmente, irá avaliar em outra coisa).

O que é exatamente a questão com os resultados?O que você espera obter?Tudo parece estar funcionando como seria de esperar-la.

Então, naturalmente, a questão de por que você está jogando com as artes das trevas de símbolo adulterar como este de qualquer maneira?:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top