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";
¡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;
}