Cambiar el valor de un puntero const

4 minutos de lectura

avatar de usuario
cscol

Tengo el siguiente fragmento de código:

void TestFunc(const void * const Var1, const float Var2)
{
  *(float*)Var1 = Var2;
}

Parece que estoy cambiando el valor del objeto const al que apunta el puntero const (gracias sharptooth), lo que no debería permitirse. El hecho es que ninguno de los compiladores que probé emitió una advertencia. ¿Cómo es esto posible?

avatar de usuario
miguel rebabas

Como mencionaron otros, el elenco elimina la “constancia” del destino en lo que respecta a la expresión. Cuando usa un molde, el compilador trata la expresión de acuerdo con el molde, siempre que el molde en sí sea válido (y los moldes de estilo C son prácticamente el gran martillo). Es por eso que no recibe un error o una advertencia. Básicamente, le estás diciendo al compilador, “cállate, sé lo que estoy haciendo, así es como debes tratar las cosas”. De hecho, las conversiones son probablemente la forma número 1 para que los programadores hagan que el compilador deje de emitir advertencias.

Su expresión de asignación puede o no ser un comportamiento indefinido. Está permitido desechar la constancia Si el objeto al que se apunta realmente no es const.

Sin embargo, si el objeto al que apunta es constante, entonces tiene un comportamiento indefinido.

void TestFunc(const void * const Var1, const float Var2)
{
  *(float*)Var1 = Var2;
}


int
main(void)
{
    float x = 1.0;
    const float y = 2.0;

    TestFunc( &x, -1.0);    // well defined (if not particularly great style)
    TestFunc( &y, -2.0);    // undefined behavior

    return 0;
}

Estás navegando en aguas peligrosas…

En general (estoy seguro de que hay excepciones), se admite la conversión para que las expresiones traten los objetos como realmente son, un comportamiento bien definido en C/C++.

Este comportamiento particular está cubierto en los estándares principalmente por declaraciones que modifican un objeto const a través de un molde (o algo así) que elimina el calificador const no está definido. La inferencia es que hacer lo mismo para un objeto no constante no está indefinido. Un ejemplo dado en el estándar C++ deja esto claro.

C90 6.5.3 – Calificadores de tipo (C99 6.7.3):

Si se intenta modificar un objeto definido con un tipo calificado const mediante el uso de un lvalue con un tipo no calificado const, el comportamiento no está definido.

C++ 7.1.5.1 Los calificadores cv

Un puntero o referencia a un tipo calificado con cv no necesita apuntar o referirse a un objeto calificado con cv, pero se trata como si lo hiciera; una ruta de acceso calificada const no se puede usar para modificar un objeto, incluso si el objeto al que se hace referencia es un objeto que no es const y se puede modificar a través de alguna otra ruta de acceso. [Note: cv-qualifiers are
supported by the type system so that they cannot be subverted without casting (5.2.11). ]

Excepto que cualquier miembro de clase declarado mutable (7.1.1) puede modificarse, cualquier intento de modificar un objeto const durante su vida útil (3.8) da como resultado un comportamiento indefinido.

[Example:

int i = 2;            //not cv-qualified
const int* cip;       //pointer to const int
cip = &i;             //OK: cv-qualified access path to unqualified
*cip = 4;             //ill-formed: attempt to modify through ptr to const

int* ip;
ip = const_cast<int*>(cip);   //cast needed to convert const int*to int*
*ip = 4;                      //defined: *ip points to i, a non-const object

const int* ciq = new const int (3);   //initialized as required
int* iq = const_cast<int*>(ciq);      //cast required
*iq = 4;                              //undefined: modifies a const object

  • Thanks for the detailed explanation. Do you happen to have a reference where this is documented for the C language? All I can find is references to const_cast in C++.

    – cschol

    Apr 21, 2009 at 13:00

  • I added the relevant material from the standards.

    – Michael Burr

    Apr 21, 2009 at 15:46

  • I appreaciate it. Thanks alot!

    – cschol

    Apr 22, 2009 at 4:31

You change the object the pointer points to, not the pointer value.

C-style cast acts like a const_cast and removes the const modifier off the pointer. The compiler now has nothing to moan about.

The cast is legal, but the behaviour is undefined.

  • That seems like a confusing answer to me. Using the cast may or may not be undefined behavior, depending on what it’s used on.

    – David Thornley

    Apr 21, 2009 at 16:16

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad