Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

258
Visualizações
No permitir que el preprocesador C use una macro dentro de otra

Estoy experimentando para ver hasta dónde puedo abusar del preprocesador C y me he topado con un problema interesante.

Tengo las siguientes definiciones de macro:

 #define if(x) if (x) #define do { #define elif(x) } else if (x) { #define else } else { #define done }

Lo que debería permitirme escribir:

 if (i == 1) do ... elif (i == 2) ... else ... done

Y funciona perfectamente bien si solo uso if y else , excepto que la introducción de elif es problemática porque la macro se expande como:

 } } else { if (x) {

debido a que el else está definido.

¿Hay alguna forma de que elif use 'raw' else sin que el preprocesador lo recoja? Creo que necesito intentar anidar múltiples definiciones para engañar al preprocesador para que pegue la palabra directamente sin analizarla, pero no estoy seguro de cómo lograrlo.

¿Alguna idea, o esto no es posible en GCC?

Editar:

En esencia, esto se puede reducir al siguiente problema:

 #define AB #define BC

Para las dos definiciones A y B dadas, ¿cómo puedo hacer que A aún se resuelva en la palabra literal B y no pase por la segunda definición y termine como C ?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Actualizar

Creo que logré solucionarlo. Utilicé eso:

 if(x) { ... }

es lo mismo que

 for(; x ;) { ... break: }

Lo que necesitamos a partir de ahí es guardar el resultado de x . No podemos reutilizarlo, ya que x podría ser una expresión con efectos secundarios. Asi que:

 int b; for(; b = (x);) { break; }

Ahora, podemos verificar b para ver si el bucle for anterior se ejecutó o no. Un patrón if-elif-else completo hecho con bucles for puede verse así:

 for(;b = (x);) { // if ... break; } for(; !b ? b=(x==1) : 0;) { // elif ... break; } for(; !b ;) { // else ... break; }

Con eso, podemos terminarlo así, pero ten cuidado. Sin embargo, esto no funcionará bien si hace un if(x) break dentro de un ciclo. Vea abajo.

 int b; // Store truth value of last if or elif #define if(x) for(;b = !!(x);) #define do { #define elif(x) break; } for(; !b ? b=!!(x) : 0;) { #define else break; } for(;!b;) { #define done break; }

Demostración: https://onlinegdb.com/Zq6Y7vm5Q

Un enfoque alternativo sin declaraciones de break :

 int b; // Store truth value of last if or elif #define if(x) for(int c=1 ; c && (b = !!(x)); c=0) #define do { #define elif(x) } for(int c=1; c && (!b ? b=!!(x) : 0); c=0) { #define else } for(int c=1; c && !b; c=0) { #define done }

Sin embargo, tenga en cuenta que ambos pueden fallar si tiene una declaración de break como esta:

 for(...) { if(x) do break; done }

Porque eso se expandiría a:

 for(...) { for(int c=1 ; c && (b = !!(x)); c=0) { break; } }

Nota:

Debería ser obvio, pero si decide usar este código (no lo haga), use mejores nombres que b y c para evitar colisiones.

Solución antigua

No es exactamente lo que pediste, pero admitiste que básicamente estás abusando del preprocesador. :)

Pero una solución fácil es usar un sinónimo de else .

 #define if(x) if (x) #define do { #define elif(x) } else if (x) { #define otherwise } else { #define done }

Demostración: https://onlinegdb.com/Cp-gYpOvm

Funciona con cero, una o múltiples instancias de elif, e independientemente de cuántos elifs, funciona con y sin otros.

over 4 years ago · Santiago Trujillo Relatório

0

Sobre la base de las ideas de klutt , aquí hay una alternativa sin la necesidad de una variable adicional, pero limitada a una sola cláusula elif :

 #define if(x) switch (!!(x)) #define do { case 1: { #define elif(x) } break; default: switch (!!(x)) { case 1: #define else } break; default: { #define done }}

Además de la deficiencia de elif , esta solución no combina bien con bucles e interruptores escritos por el usuario. Estos casos serán mal manejados:

 for(...) { if(...) break; } switch (x) { case 0: if (...) break; else { y = 42; break; } ... }

Para su propósito, usar pseudo-palabras clave en mayúsculas parece un mejor enfoque (y deliberadamente feo).

 #define IF(x) if (x) #define DO { #define ELIF(x) } else if (x) { #define ELSE } else { #define DONE }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda