punteros puntero memoria matrices lenguaje dinamica declarar como aritmetica apuntadores c++ pointers static-members undefined-behavior dereference

c++ - memoria - punteros void lenguaje c



¿Por qué el código llama explícitamente a un método estático a través de un puntero nulo? (1)

Las funciones de miembro estático se agregaron a C ++ en 1989, en la Versión 2.0 del Sistema de lenguaje AT & T C ++ (preestandarización). Antes de eso, la palabra clave static no se podía usar para declarar funciones miembro estáticas, por lo que los autores del código usaban soluciones temporales, principalmente la que usted ha observado de indirectar un puntero nulo.

En las lecturas seleccionadas que acompañan a la versión 2.0 del sistema de lenguaje AT & T C ++, en la sección 1-22, Stroustrup escribe:

También se observó que el código no portable, como por ejemplo:

((X*)0)->f();

se usó para simular funciones miembro estáticas. Este truco es una bomba de tiempo porque tarde o temprano alguien hará un f() que se usa de esta manera virtual y la llamada fallará horriblemente porque no hay un objeto X en la dirección cero. Incluso cuando f() no es virtual, tales llamadas fallarán en algunas implementaciones de vinculación dinámica.

Su código se escribió para compilarse en Cfront 1.0 o por alguien que no tenía conocimiento al momento de agregar las funciones de miembro estático al idioma.

La anotación de la función miembro con static es de hecho un acertijo, como Cheers y hth. - Alf ha observado; Cfront 1.0 habría rechazado ese código con:

error: member Method() cannot be static

entonces no puede haber estado allí inicialmente. Creo que Potatoswatter probablemente sea correcto; static se agregó en una fecha posterior para documentar y aplicar el atributo de método estático de Method , una vez que se pudo garantizar la disponibilidad de un compilador de C ++ 2.0, pero sin actualizar el código de llamada. Para confirmar esto, deberá entrevistar al programador original o al menos examinar el historial de control de origen (si existe).

He visto código como este en un par de proyectos antiguos:

class Class { static void Method() {} }; ((Class*)0)->Method();

Este código contiene un comportamiento indefinido porque incluye la eliminación de referencia de un puntero nulo (no importa lo que suceda después). Realmente no tiene sentido, el elenco está ahí para alimentar el nombre del tipo al compilador y quien escribió el código anterior podría haber escrito esto en su lugar:

Class::Method();

y el último estaría bien.

¿Por qué alguien escribiría el código anterior? ¿Es un idioma conocido de algunos viejos tiempos o qué?