9
votes

Les littéraux composés et les macros semblables à la fonction: bugs dans GCC ou la norme C?

en C99, nous avons des littéraux composés et ils peuvent être transmis à des fonctions comme dans: xxx

Cependant, si f n'est pas une fonction mais plutôt un Macro en forme de fonction, Barfs GCC à ce sujet en raison du préprocesseur qui l'analysant pas comme un argument, mais comme deux arguments, " (int [2]) {1 " et "code> 2} ".

est-ce un bogue dans GCC ou dans la norme C? Si c'est ce dernier, cela règle à peu près toutes les utilisations transparentes de macros en forme de fonction, qui ressemblent à un énorme défaut ...

EDIT: À titre d'exemple, on pourrait Attendez-vous à ce que ce qui suit soit un fragment de programme conforme: xxx

mais depuis fgetc. / code> pourrait être mis en oeuvre comme une macro (bien que nécessaire pour protéger son argument et protéger son argumentation. Ne pas l'évaluer plus d'une fois), ce code serait effectivement incorrect. Cela me semble surprenant.


6 commentaires

C'est normal et standard. N'oubliez pas que les macros ont existé depuis longtemps avant l'une de ces autres gubbins, et ils ne sont pas aussi intelligents.


GCC 4.5.2 avec le -std = c99 option accepte macro_fx (((int [2]) {1, 2})) Pour regrouper l'expression dans votre exemple dans votre exemple un argument.


Je suis au courant de la solution de contournement. Mais cela signifie que les macros semblables à la fonction ne peuvent pas vraiment être "comme une fonction" en C99. Avant les littéraux composés, je ne pense pas que la langue n'avait aucune construction où cette question importait.


... Et Steve va et me prouve tort!


Ce n'est pas un bug de rien. C et CPP sont langues séparées qui ont une boîte à outils intégrée, et le RPC n'est pas (et n'est pas autorisé à être) au courant des constructions de C. Si c'était c'était, vous ne seriez pas capable de faire des choses comme le faire / pendant Trick, blocs personnalisés basé sur pour ou macros Manger des types / des opérateurs (au moins l'un d'entre eux - offsetof - est dans la norme).


@LeShenko: En ce sens, il est sans doute un bug de la norme C, dans ce C permet aux définitions de macro-macro-fonctions pour les fonctions standard malgré elles ne se comportent pas réellement identique aux fonctions. Mais comme le montre la réponse de Steve, c'était déjà le cas que ceux-ci pouvaient se comporter de manière inattendue et étrange à moins que vous n'utilisiez des parenthèses supplémentaires, donc si quelque chose dans la norme devrait être modifié, il s'agit probablement d'ajouter un langage ATENDANT que les programmes conformes doivent être Conscient de cela et utilisez des parenthèses où la question pourrait les affecter.


3 Réponses :


6
votes

Ceci est par la norme C, similaire à la manière dont C ++, ce qui suit est un problème:

f(((int[2]){ 1, 2 }));
  ^                ^


0 commentaires

1
votes

Dans la mesure où il s'agit d'un bug, c'est avec la norme, pas GCC (c'est-à-dire à cet égard, je pense que GCC fait quelle est la norme requise).


0 commentaires

10
votes

Ce "bogue" existe dans la norme depuis C89:

#include <stdio.h>

void function(int a) {
    printf("%d\n", a);
}

#define macro(a) do { printf("%d\n", a); } while (0)

int main() {
    function(1 ? 1, 2: 3); /* comma operator */
    macro(1 ? 1, 2: 3);    /* macro argument separator - invalid code */
    return 0;
}


3 commentaires

+1 Excellente trouvaille pour un cas où cette question existe avant la C99. Je suppose que des parenthèses supplémentaires sont simplement nécessaires partout où une fonction pourrait réellement être définie comme une macro de la fonction comme une fonction ...


@ R. leur dit, ce que je pense que cela saura toujours sauver une macro de la fonction variable.


Hmm, je suppose qu'une macro de la fonction variable est en fait une solution à ce problème! C'est-à-dire qu'une implémentation pourrait faire #define fgets (...) __inline_fgets (__ va_args __) et le faire fonctionner dans tous les cas. ( #define fgets __inline_fgets D'autre part n'est pas valide pour une implémentation à faire car il rendra le nom de la fonction solitaire sans que l'opérateur d'appel de fonction n'est évalué au pointeur de fonction incorrect, c'est-à-dire des pointeurs différents dans différents. Unités de traduction.)