2017-02-19 4 views
0

Это код.Почему мой компилятор не показывает ошибку, когда я хочу изменить указатель на постоянное целое число?

int main() 
    {int v=2; 
    const int *p=&v; 
    ++v; //Option 1: Does work, but why should it? 
    // ++*p; //Option 2: Does not work 
    }    

Компилятор выдает ошибку для варианта 2, как и ожидалось. Но он идет с опцией 1, когда она изменяет содержимое указателя на постоянное целое число. Зачем? Или я понимаю что-то неправильно в отношении импликации const? Он применим только для переменных в куче, а не для стека?

+3

'V' является not const, почему компилятор не должен изменять его? 'const' не означает, что« этот объект никогда не может быть изменен »- он означает только« этот объект не может быть изменен с помощью этого указателя или ссылки ». –

+0

@IgorTandetnik Объект const никогда не может быть изменен. Вы говорите о не-top-level const-qualifier на указателе (важное различие - 'const' означает разные вещи в разных контекстах) –

+0

@ M.M Я действительно несколько упрощал - возможно, слишком много. Хотя один из способов думать об объекте const заключается в том, что он не может быть изменен, потому что вы никогда не сможете (юридически) получить указатель, не являющийся константой, или ссылку на него. –

ответ

1

Или я понимаю что-то неправильно о импликации const?

Да.

Когда у вас есть:

int v = 2; 
const int *p=&v; 

Вам не разрешено изменять объект через p, но вы по-прежнему разрешено изменять объект непосредственно через v. Вы также можете изменить объект с помощью другого указателя.

int* p2 = &v 
*p2 = 10; // OK. 
0

const не на самом деле означает «постоянный», это в основном означает «только для чтения». Когда вы определяете указатель на объект const, это не означает, что объект никогда не может измениться - это просто означает, что вы не можете записать этому объекту с помощью этого указателя.

На самом деле, это совершенно допустимо (а иногда и значимо), чтобы указать, что объект равен const (так что вы не можете его изменить) и volatile (что указывает на то, что что-то еще может его изменить). Например, в дни MS-DOS BIOS поддерживал таймер с адресом 40:6c (смещение 0x6c в сегменте 0x40), которое обновлялось каждые ~ 55 мс, но вы не должны писать его напрямую, поэтому вы можете определить указатель на него нравится:

long const volatile *bios_timer = MK_FP(0x40, 0x6c); 

Таким образом, попытки записать на это место (по крайней мере, через этот указатель) был не разрешено, но значение, которое вы хотите читать из него изменится на регулярной и постоянной основе.

[Обратите внимание, что вопреки тому, как это может показаться выше: это (предположительно) до сих пор существует - но с защищенным режимом OS, пытается получить к нему доступ непосредственно в пользовательском режиме, несомненно, не в состоянии.]

Смежные вопросы