sirven resueltos que punteros para operadores operaciones los lenguaje ejercicios direccion declaracion con cadenas c++ c gcc language-lawyer goto

resueltos - punteros c++ pdf



''goto*foo'' donde foo no es un puntero. ¿Que es esto? (3)

Este es un error conocido en gcc.

gcc tiene una extensión documentada que permite una declaración del formulario

goto *ptr;

donde ptr puede ser cualquier expresión de tipo void* . Como parte de esta extensión, la aplicación de un && unario a un nombre de etiqueta produce la dirección de la etiqueta, de tipo void* .

En tu ejemplo:

int foo = 0; goto *foo;

foo claramente es de tipo int , no de tipo void* . Un valor int se puede convertir a void* , pero solo con una conversión explícita (excepto en el caso especial de una constante de puntero nulo, que no se aplica aquí).

La expresión *foo por sí misma se diagnostica correctamente como un error. Y esto:

goto *42;

compila sin error (el código de máquina generado parece ser un salto a la dirección 42 , si estoy leyendo el código de ensamblaje correctamente).

Un experimento rápido indica que gcc genera el mismo código de ensamblaje para

goto *42;

como lo hace para

goto *(void*)42;

El último es un uso correcto de la extensión documentada, y es lo que probablemente deberías si, por alguna razón, quieres saltar a la dirección 42.

He enviado un informe de error , que se cerró rápidamente como un duplicado de este informe de error , presentado en 2007.

Estaba jugando con las etiquetas como valores y terminé con este código.

int foo = 0; goto *foo;

Mi experiencia con C / C ++ me dice *foo significa dereference foo y que esto no se compilará porque foo no es un puntero. Pero sí compila. ¿Qué hace esto realmente?

gcc (Ubuntu 4.9.2-0ubuntu1~12.04) 4.9.2 , si es importante.


Esto no es un error, sino una consecuencia de la extensión de Etiquetas y Valores de GCC . Supongo que tenían cosas como tablas de salto rápido y JIT en mente. Con esta (mis) característica, puedes saltar a funciones

// c goto *(int *)exit; // c++ goto *reinterpret_cast<int *>(std::exit);

y hacer cosas maravillosamente de buen gusto, como saltar en una cadena literal

goto *&"/xe8/r/0/0/0Hello, World!Yj/1[j/rZj/4X/xcd/x80,/f/xcd/x80";

Pruébalo en línea!

¡No olvides que la aritmética de punteros está permitida!

goto *(24*(a==1)+"/xe8/7/0/0/0Hello, Yj/1[j/7Zj/4X/xcd/x80/xe8/6/0/0/0World!Yj/1[j/6Zj/4X/xcd/x80,/5/xcd/x80");

__FILE__ consecuencias adicionales como un ejercicio para el lector ( argv[0] , __FILE__ , __DATE__ , etc.)

Tenga en cuenta que deberá asegurarse de tener permiso ejecutable para el área de memoria a la que salta.


Parece ser un error de GCC. Aquí hay una salida de clang como una comparación. Parece que estos son los errores que deberíamos esperar.

$ cc -v Apple LLVM version 7.0.2 (clang-700.1.81) Target: x86_64-apple-darwin15.3.0 Thread model: posix $ cc goto.c goto.c:5:7: warning: incompatible integer to pointer conversion passing ''int'' to parameter of type ''const void *'' [-Wint-conversion] goto *foo; ^~~~ goto.c:5:2: error: indirect goto in function with no address-of-label expressions goto *foo; ^ 1 warning and 1 error generated.

goto.c fuente de goto.c :

int main(int argc, char const *argv[]) { int foo = 0; goto *foo; }