¿Qué significa && en void * p = && abc;

102

Me encontré con un fragmento de código void *p = &&abc;. ¿Cuál es el significado de &&aquí? Sé acerca de las referencias de rvalue pero creo que se &&usa en este contexto es diferente. ¿Qué &&indica en void *p = &&abc;?

Brent Arias
fuente
14
¿Dónde viste esto?
user541686
3
También me gustaría saber dónde ha visto esto.
Flavius

Respuestas:

154

&&es la extensión de gcc para obtener la dirección de la etiqueta definida en la función actual.

void *p = &&abc es ilegal en los estándares C99 y C ++.

Esto se compila con g ++.

Prasoon Saurav
fuente
42
Ahora imagine cuán mejores programadores serían todos si gcc tuviera -pedantic por defecto. Entonces la gente aprendería C en lugar de información irrelevante sobre gnus.
Lundin
4
Qué truco. Si inventan una nueva sintaxis para los punteros de etiquetas, también deberían inventar un nuevo tipo en lugar de usarla void*.
Mark Ransom
1
@Prasoon Saurav: Quien haya votado en contra probablemente desaprueba la función y se está desquitando contigo.
Chuck
@Lundin: Lo mismo puede decirse de la mayoría de los compiladores. __forceinline? __declspec(naked)? Uno de mis MSVCisms favoritos es:, template<typename T> class X { friend T; }que no es válido C ++ 03.
Sebastian Mach
El segundo enlace está muerto.
Cœur
96

Como averiguarlo

Esa es la dirección de una etiqueta y es una característica específica de GCC .

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

Podrías haberlo descubierto tú mismo probando:

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

En cuyo caso GCC dice:

error: etiqueta 'a' usada pero no definida

Debajo del capó - montaje

Necesita saber ensamblador para entender esto realmente, pero trataré de explicarle qué significa la dirección de una etiqueta.

Después de que el sistema operativo carga el archivo .exe desde el disco, un componente del sistema operativo llamado "el cargador" (Windows tiene el "cargador PE", Linux tiene "cargador ELF" o incluso otros, si están compilados en el kernel), hace una "virtualización" de ese programa, convirtiéndolo en un proceso.

Este proceso piensa que es el único en RAM y tiene acceso a toda la RAM (es decir, 0x00000000-0xFFFFFFFF en una máquina de 32 bits).

(lo anterior es solo una breve descripción de lo que está sucediendo, realmente necesita aprender a ensamblar para comprenderlo completamente, así que tenga paciencia conmigo)

Ahora, la etiqueta en un código fuente es básicamente una dirección. "ir a etiqueta;" no hace nada más que un salto a esa dirección (piense en el puntero de instrucción en ensamblador). Esta etiqueta almacena esta dirección RAM, y así es como puede encontrar esa dirección.

Una vez que haya aprendido ASM, se dará cuenta de que esa dirección apunta a una instrucción dentro de la .textsección del ejecutable. los.text sección es la que contiene el código (binario) de su programa para ser ejecutado.

Puede inspeccionar esto con:

objdump -x a.out

Un ejemplo practico

Como se describe en GCC , puede usar esto para inicializar una tabla de salto. Algunos generadores de escáneres como re2c (consulte el -gparámetro) lo usan para generar escáneres más compactos. Tal vez incluso haya un generador de analizador sintáctico que emplee la misma técnica.

Flavio
fuente
4
Compile con -std = c99 -pedantic.
Lundin
2
Es muy importante mencionar que es una extensión de GCC, y no una parte central del lenguaje
jalf
1
Eso es bastante impresionante Flavius.
Octavian A. Damiean
1
Me gusta este tipo de respuesta, es necesario enseñar a más personas a encontrar respuestas en lugar de simplemente que se les diga.
Letseatlunch
1
Gracias por la explicación en profundidad. Aprecio el análisis relacionado con la Asamblea.
CᴴᴀZ