Considerar este código:

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)

El resultado esperado es X = 1 and VA_ARGS = 2, 3 para ambas macros, y eso es lo que estoy consiguiendo con GCC, sin embargo, MSVC expande esto como:

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =

Que es, __VA_ARGS__ se expande como un solo argumento, en lugar de ser desglosado en varios.

Alguna forma de evitar esto?

  • Mi primer pensamiento sería conseguir un mejor compilador. Si este es el primer y más grave error que he encontrado en MSVC, usted está en un MONTÓN de sorpresas…
  • No es una opción 😛
InformationsquelleAutor uj2 | 2011-02-27

3 Comentarios

  1. 45

    MSVC del preprocesador parece comportarse de manera muy diferente de la estándar
    la especificación.

    Probablemente la siguiente solución ayudará a:

    #define EXPAND( x ) x
    #define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
    #define G(...) EXPAND( F(__VA_ARGS__) )
    • __VA_ARGS__ no es parte del estándar de C++ todavía. ¿El proyecto de norma se especifica realmente lo que el comportamiento debe ser en este caso?
    • Lo siento, ya no tengo la capacidad, no puedo explicar el preproceso en el próximo estándar de C++ en detalle aquí, pero es poco probable que sea muy diferente de la C99.
    • Podría alguien por favor explicarme esto ? Es «y VA_ARGS = VA_ARGS» una pieza válida de código de C o es sólo un texto legible por humanos que está aquí como un comentario ? si este código es valido, lo que es «y VA_ARGS = VA_ARGS» haciendo ? Gracias.
    • Fue allí, en la pregunta original. Es legible por humanos del texto que se muestra el resultado de la expansión de macro después de que el preprocesador se hace con ella. O más bien. es más como una plantilla: Es el texto literal, excepto para el __VA_ARGS__ bits, la cual se expandió (no Es válido el código C, pero sólo nos interesa el preprocesamiento de aquí.)
    • Por favor puede explicar, ¿por qué funciona esto?
    • Lo siento, no puedo explicar la razón técnica. Vi Microsoft Conectarse a la página de informes de este error antes, pero la página parece no disponible ahora. Creo que este comportamiento es un error de MSVC, y EXPAND macro en la respuesta es una pura solución.
    • No sé C que bien, pero and es un C++ alias para &&, junto con or = ||, etc. No pude encontrar en C listas de palabras clave, pero me estoy dando cuenta que es difícil buscar palabras como «y» y «o» excluir «C++», mientras que la búsqueda para «C» (me encantaría saber cómo comunicar » me refiero a lo que me dijo que para los motores de búsqueda cuando citas a solas no hacer el trabajo.) Si estás usando C macros pero compilar C++, and es legible y válido; supongo que la ambigüedad visual (&& o &?) y, posiblemente, la barrera del idioma o precedente/convenio/estilo hacen que sea raro. en.cppreference.com/w/cpp/keyword/and
    • Oh, creo que puedo ver…digamos que __VA_ARGS__ es 1, 2 en lugar de la simplicidad. EXPAND(x) x toma F(__VA_ARGS__)) y lo reemplaza con, literalmente, F(1, 2) para que F(1, 2) se procesa en lugar de F(__VA_ARGS__) donde __VA_ARGS__ es visto como una sola entidad, si que tiene sentido…

  2. 21

    He publicado el siguiente problema de soporte técnico de Microsoft:

    El siguiente programa da error de compilación porque el precompilador
    expande __VA_ARGS__ incorrectamente:

    #include <stdio.h>
    
    #define A2(a1, a2) ((a1)+(a2))
    
    #define A_VA(...) A2(__VA_ARGS__)
    
    int main(int argc, char *argv[])
    {
        printf("%d\n", A_VA(1, 2));
        return 0;
    }

    El preprocesador se expande el printf para:
    printf(«%d\n», ((1, 2)+()));

    lugar de
    printf(«%d\n», ((1)+(2)));

    He recibido la siguiente insatisfactoria respuesta de un compilador de Microsoft team developer:

    Hola: El compilador de Visual C++ se comporta correctamente en este caso. Si se combinan la regla de que las fichas que coincidan con el ‘…’ en la inicial de macro invocación se combinan para formar una sola entidad (16.3/p12) con la regla de que la sub-macros se expanden antes argumento de reemplazo (16.3.1/p1), a continuación, en este caso el compilador cree que A2 se invoca con un argumento único: de ahí el mensaje de error.

    • Gracias por pasar a lo largo de MS de la justificación. Parece que están interpretando «combinan para formar un único elemento» en 16.3.1/p12 como «combinan para formar una sola, de forma permanente indivisible preprocesador token», que parece ser menos útil. Yo esperaría que el sustituido tokens para ser reseparated al menos para la reexploración paso dado en 16.3.4, que parece ser lo que otros compiladores están haciendo.
    • Estoy totalmente de acuerdo, pero estoy evidentemente mimados por el GCC y Clang. Puede usted pensar en un caso de uso para el MSVC comportamiento, o es sólo una cuestión de coherencia la coherencia de amor a pesar de expressibility? Estoy fuera de mi elemento, pero «…En este caso el compilador cree que…» no suena muy convincente, mucho menos útil para cualquiera que esté tratando de escribir agnóstico código. Tengo un par de ideas para soluciones, pero mi partición de Windows está fuera de la comisión. Me gustaría ver a alguien intento en cualquier caso. Perdón por la perorata, y/o necropost.
    • Por lo que vale, aquí está otro bug sobre el mismo tema, donde el equipo admite que es un error, pero dice que no es lo suficientemente alta prioridad a la revisión (hace 7 años).
  3. 1

    Qué versión de MSVC estás usando? Usted necesitará Visual C++ 2010.

    __VA_ARGS__ fue introducido por primera vez por C99. MSVC nunca trató de apoyo C99, por lo que el apoyo no se ha agregado.

    Ahora, sin embargo, __VA_ARGS__ está incluido en el nuevo estándar de C++, C++de 2011 (anteriormente conocido como C++0x), que Microsoft al parecer, los planes de apoyo, por lo que se ha apoyado en las últimas versiones de MSVC.

    Por CIERTO, usted tendrá que utilizar un .cpp sufijo para el archivo de origen para obtener este apoyo. MSVC no ha actualizado su C frontend para un largo tiempo.

Dejar respuesta

Please enter your comment!
Please enter your name here