Que signifie && dans void * p = && abc;

102

Je suis tombé sur un morceau de code void *p = &&abc;. Quelle est la signification d' &&ici? Je connais les références rvalue mais je pense &&qu'utilisé dans ce contexte est différent. Qu'est-ce que cela &&indique void *p = &&abc;?

Brent Arias
la source
14
Où avez-vous vu cela?
user541686
3
J'aimerais aussi savoir où vous avez vu ça.
Flavius

Réponses:

154

&& est l'extension de gcc pour obtenir l'adresse de l'étiquette définie dans la fonction courante.

void *p = &&abc est illégal dans les standards C99 et C ++.

Cela compile avec g ++.

Prasoon Saurav
la source
42
Imaginez maintenant à quel point tout le monde serait meilleur si gcc avait -pedantic par défaut. Ensuite, les gens apprendraient C au lieu d'informations non pertinentes sur les gnus.
Lundin
4
Quel hack. S'ils inventent une nouvelle syntaxe pour les pointeurs d'étiquettes, ils devraient également inventer un nouveau type pour celui-ci au lieu d'utiliser void*.
Mark Ransom
1
@Prasoon Saurav: Quiconque a voté défavorablement désapprouve probablement la fonctionnalité et la prend à votre encontre.
Chuck
@Lundin: On peut dire la même chose de la plupart des compilateurs. __forceinline? __declspec(naked)? Un de mes MSVCism préférés est:, template<typename T> class X { friend T; }qui est invalide C ++ 03.
Sebastian Mach
Le deuxième lien est mort.
Cœur
96

Comment le découvrir

C'est l'adresse d'un label et c'est une fonctionnalité spécifique à GCC .

int main(void) {
    void* startp;
s:
    startp = &&s;
    printf("the assignment above starts at address %p\n", startp);
    return 0;
}

Vous auriez pu le découvrir vous-même en testant:

int main(void) {
    void* startp;
    int a;
    startp = &&a;
    printf("startp=%p\n", startp);
    return 0;
}

Dans ce cas, GCC dit:

erreur: étiquette 'a' utilisée mais non définie

Sous le capot - montage

Vous devez connaître l'assembleur pour vraiment comprendre cela, mais je vais essayer de vous expliquer ce que signifie une adresse d'étiquette.

Une fois que le système d'exploitation a chargé le fichier .exe à partir du disque, un composant du système d'exploitation appelé "le chargeur" ​​(Windows a le "PE Loader", Linux a "ELF loader" ou peut-être même d'autres, s'ils sont compilés dans le kernel), il fait une "virtualisation" de ce programme, le transformant en processus.

Ce processus pense qu'il est le seul dans la RAM et qu'il a accès à toute la RAM (c'est-à-dire 0x00000000-0xFFFFFFFF sur une machine 32 bits).

(ce qui précède n'est qu'un bref aperçu de ce qui se passe, vous devez vraiment apprendre l'assemblage pour le comprendre pleinement, alors soyez avec moi)

Maintenant, l'étiquette dans un code source est essentiellement une adresse. "goto label;" ne fait rien d'autre qu'un saut vers cette adresse (pensez au pointeur d'instruction dans l'assemblage). Cette étiquette stocke cette adresse RAM, et c'est ainsi que vous pouvez trouver cette adresse.

Après avoir appris l'ASM, vous vous rendrez compte que cette adresse pointe vers une instruction dans la .textsection de l'exécutable. La .textsection est celle qui contient le code (binaire) de votre programme à exécuter.

Vous pouvez l'inspecter avec:

objdump -x a.out

Un exemple pratique

Comme décrit dans GCC , vous pouvez l'utiliser pour initialiser une table de saut. Certains générateurs de scanners comme re2c (voir le -gparamètre) l'utilisent pour générer des scanners plus compacts. Peut-être qu'il existe même un générateur d'analyseur utilisant la même technique.

Flavius
la source
4
Compilez avec -std = c99 -pedantic.
Lundin
2
Il est assez important de mentionner qu'il s'agit d'une extension GCC et non d'une partie essentielle du langage
jalf
1
C'est assez impressionnant Flavius.
Octavian A. Damiean
1
J'aime ce genre de réponse, il faut apprendre à plus de gens comment trouver des réponses plutôt que de simplement se faire dire.
Letseatlunch
1
Merci pour l'explication détaillée. J'ai apprécié l'analyse liée à l'Assemblée.
CᴴᴀZ