Изменение значения константного указателя - PullRequest
4 голосов
/ 21 апреля 2009

У меня есть следующий фрагмент кода:

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

Похоже, я изменяю значение объекта const, на который указывает указатель const (благодаря sharptooth), что недопустимо. Дело в том, что ни один из опробованных мной компиляторов не выдал предупреждение. Как это возможно?

Ответы [ 3 ]

11 голосов
/ 21 апреля 2009

Как уже упоминалось, приведение удаляет «константность» пункта назначения в том, что касается выражения. Когда вы используете приведение, компилятор обрабатывает выражение в соответствии с приведением - до тех пор, пока приведение само по себе допустимо (и приведение в стиле C в значительной степени является большим молотком). Вот почему вы не получаете сообщение об ошибке или предупреждение. По сути, вы говорите компилятору: «Молчи, я знаю, что делаю, вот как ты должен относиться к вещам». Фактически, приведение - это, вероятно, # 1 способ для программистов заставить компилятор прекратить выдавать предупреждения.

Ваше выражение присваивания может быть или не быть неопределенным поведением. Разрешается выбрасывать константу , если объект, на который фактически указывает, не является константой.

Однако, если объект, на который указывает объект, является const, то у вас неопределенное поведение.

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

Вы идете по опасным водам ...

В целом (я уверен, что есть исключения), поддерживается приведение, чтобы выражения обрабатывали объекты так, как они есть на самом деле, хорошо определенное поведение в C / C ++.

Это конкретное поведение в стандартах охватывается в основном заявлениями, которые изменяют const-объект посредством преобразования (или чего-либо), удаляющего квалификатор const, не определено. Вывод заключается в том, что выполнение того же для неконстантного объекта не является неопределенным. Пример, приведенный в стандарте C ++, проясняет это.

C90 6.5.3 - Классификаторы типов (C99 6.7.3):

Если предпринята попытка изменить объект, определенный с помощью типа с константой, посредством использования lvalue с неконстантным типом, поведение не определено.

C ++ 7.1.5.1 Классификаторы cv

Указатель или ссылка на тип с квалификацией cv не обязательно должен указывать или ссылаться на объект с квалификацией cv, но он обрабатывается так, как если бы он был; квалифицированный константный путь доступа не может использоваться для изменения объекта, даже если упомянутый объект является неконстантным объектом и может быть изменен через какой-либо другой путь доступа. [Примечание: cv-квалификаторы поддерживается системой типов, так что они не могут быть уничтожены без приведения (5.2.11). ]

За исключением того, что любой член класса, объявленный mutable (7.1.1), может быть изменен, любая попытка изменить const объект в течение его жизни (3.8) приводит к неопределенному поведению.

...

[Пример: * * тысяча тридцать-один

...

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
2 голосов
/ 21 апреля 2009

Вы изменяете объект, на который указывает указатель, а не значение указателя.

Приведение в стиле C действует как const_cast и удаляет модификатор const из указателя. Теперь компилятору нечего стонать.

1 голос
/ 21 апреля 2009

Актерский состав допустим, но поведение не определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...