web-dev-qa-db-fra.com

Que fait un opérateur && lorsqu'il n'y a pas de côté gauche en C?

J'ai vu un programme en C qui avait du code comme celui-ci:

static void *arr[1]  = {&& varOne,&& varTwo,&& varThree};

varOne: printf("One") ;
varTwo: printf("Two") ;
varThree: printf("Three") ;

Je suis confus sur ce que le && le fait parce qu'il n'y a rien à sa gauche. Est-il évalué comme nul par défaut? Ou s'agit-il d'un cas particulier?

Modifier: Ajout de plus d'informations pour rendre la question/le code plus clair pour ma question. Merci à tous pour l'aide. C'était le cas de l'extension spécifique à gcc.

50
Joshua

C'est une extension spécifique à gcc, un opérateur unaire && Qui peut être appliqué à un nom d'étiquette, donnant son adresse sous la forme d'une valeur void*.

Dans le cadre de l'extension, goto *ptr; Est autorisé où ptr est une expression de type void*.

C'est documenté ici dans le manuel de gcc.

Vous pouvez obtenir l'adresse d'une étiquette définie dans la fonction courante (ou une fonction contenante) avec l'opérateur unaire &&. La valeur a le type void *. Cette valeur est une constante et peut être utilisée partout où une constante de ce type est valide. Par exemple:

void *ptr;
/* ... */
ptr = &&foo;

Pour utiliser ces valeurs, vous devez pouvoir passer à une. Cela se fait avec l'instruction goto calculée, goto *exp;. Par exemple,

goto *ptr;

Toute expression de type void * Est autorisée.

Comme zwol le fait remarquer dans un commentaire, gcc utilise && Plutôt que le plus évident & Car une étiquette et un objet du même nom peuvent être visibles simultanément, ce qui rend &foo Potentiellement ambigu si & signifie "adresse de l'étiquette". Les noms d'étiquette occupent leur propre espace de nom (pas dans le sens C++) et ne peuvent apparaître que dans des contextes spécifiques: définis par une étiquette-déclaration , comme cible d'une instruction goto, ou, pour gcc, comme l'opérande d'unaire &&.

60
Keith Thompson

Il s'agit d'une extension gcc, connue sous le nom de "Labels as Values". Lien vers la documentation gcc .

Dans cette extension, && est un opérateur unaire qui peut être appliqué à une étiquette . Le résultat est une valeur de type void *. Cette valeur peut être déréférencée ultérieurement dans une instruction goto pour provoquer l'exécution de sauter à cette étiquette. De plus, l'arithmétique des pointeurs est autorisée sur cette valeur.

L'étiquette doit avoir la même fonction; ou dans une fonction englobante au cas où le code utilise également l'extension gcc de "fonctions imbriquées".

Voici un exemple de programme où la fonctionnalité est utilisée pour implémenter une machine à états:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    void *tab[] = { &&foo, &&bar, &&qux };

    // Alternative method
    //ptrdiff_t otab[] = { &&foo - &&foo, &&bar - &&foo, &&qux - &&foo };

    int i, state = 0;

    srand(time(NULL));

    for (i = 0; i < 10; ++i)
    {
        goto *tab[state];

        //goto *(&&foo + otab[state]);

    foo:
        printf("Foo\n");
        state = 2;
        continue;
    bar:
        printf("Bar\n");
        state = 0;
        continue;
    qux:
        printf("Qux\n");
        state = Rand() % 3;
        continue;
    }
}

Compilation et exécution:

$ gcc -o x x.c && ./x
Foo
Qux
Foo
Qux
Bar
Foo
Qux
Qux
Bar
Foo
16
M.M