const в теле функций C ++

Я понял, что если я определю const int в теле функции c ++, а затем использую адресную арифметику, чтобы изменить значение константы (ее в стеке, не так ли?). я получил этот код:

const int a = 10;
int b = 100;

int * c = &b;
c++;

cout << "&a: " << &a << endl;
cout << " c: " << c << endl;*c = 100500;

cout << " a: " << a << endl;
cout << "*c: " << *c << endl;

и я получил этот вывод

&a: 0x7ffff63866a8
c: 0x7ffff63866a8

a: 10
*c: 100500

Итак, адреса одинаковы, но значения разные. Может кто-нибудь объяснить мне этот результат? Спасибо!
постскриптум я пробовал на GCC, Clang и VS

-5

Решение

const int a = 10;
int b = 100;

ХОРОШО.

int * c = &b;

Хорошо, но глупо, и мой глюкометр начинает вертеться.

c++;

Баг-о-метр теперь в желтой зоне.

cout << "&a: " << &a << endl;

Хорошо

*c = 100500;

Баг-о-метр привязан. Неопределенное поведение вызвано. Мир взрывается, тебя увольняют.

c++ перемещает указатель к следующему int в памяти. С указателем все в порядке, но все, что вы можете использовать c на данный момент, чтобы сравнить указатель к другому указателю. Вы не можете разыменовать указатель в любом случае. Но это то, что вы делаете, когда пытаетесь назначить через него.

Что будет дальше, не имеет значения и, честно говоря, вводит в заблуждение. Вы считать тот c теперь указывает на ту же память, что и bи, возможно, это так. Но это произошло только благодаря неопределенному поведению. Вы могли бы также считать что значение *c это то, что вы ожидаете, но этот результат неверен. Может быть, а может и нет. Вы разбили флакон, когда открыли коробку — кошка мертва. И ваша программа тоже.

И, кстати, если вы пытаетесь обмануть компилятор, чтобы вы могли изменить constне — строго запрещено менять const с помощью любых средств.

Eсть const_cast в C ++, но это также не механизм, который вы можете использовать для изменения const,

2

Другие решения

Может кто-нибудь объяснить мне этот результат?

Как и при любой попытке доступа к объектам недопустимыми способами с помощью неверной арифметики указателей или других махинаций: неопределенное поведение.

Здесь происходит то, что компилятор предполагает, что значение a не изменится, и оптимизировать его, чтобы быть постоянной времени компиляции. Это разрешено делать, так как вы объявили это const и тем самым заявил, что это не изменится.

это в стеке, не так ли?

Так как вы также берете его адрес (когда вы печатаете &a) он получает адрес в стеке; но программе не нужно читать с этого адреса, чтобы получить значение, поскольку оно уже известно как 10.

Конечно, все это не определено, поэтому программа будет такой же действительной, если она закажет вам пиццу.

5

Ваша программа имеет неопределенное поведение, написанное на всем протяжении …

Предположение, что увеличение адреса b заставит вас a это подделка, это могло или не могло. Затем вы используете то, что называется в стандарте небезопасно полученный указатель изменить объект const (a) который также является неопределенным поведением. Все может случиться.

Что действительно происходит (в вашей реализации, объяснение ваших результатов, но вы не можете зависеть от этого, так как это неопределенное поведение) что вы заставили выделение a в стеке, взяв его адрес, и вы получите указатель на него. Вы изменили это значение, и адрес в памяти обновился. Но в выражении: cout << " a: " << a << endl; компилятор знает тот a является константой, и, следовательно, ее значение может быть только 10, поэтому он преобразовал код в cout << " a: " << 10 << endl; чтобы избежать необходимости идти в память, чтобы получить значение.

3

это в стеке, не так ли?

Нет, ваши ожидания неверны. C ++ не имеет никакого понятия о стеке, тем более о том, как разные автоматические переменные хранятся в памяти относительно друг друга. То, что вы пытаетесь сделать, это простое неопределенное поведение.

В вашем случае компиляторы оптимизируют a далеко, потому что они разрешены стандартом, и результаты, которые вы получаете, не должны иметь никакого смысла, так как в любом случае это UB.

2

Компилятор C ++ будет просто предполагать, что вы никогда не будете пытаться изменить значение const переменная.

Это не означает, что если вы это сделаете, вы получите ошибку … просто то, что авторы компилятора могут игнорировать то, что должно произойти, и все, что происходит, будет классифицировано как «ваша ошибка».

0

СПССК:

#include <stdio.h>

int main ()
{
const int a = 10;
int b = 100;
int *c = &b;
printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
a, b, *c, (void *)&a, (void *)&b, (void *)c);

c++;  // "c" now invalid
printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
a, b, *c, (void *)&a, (void *)&b, (void *)c);

*c = 100500;  // Undefined behavior!
printf ("a=%d, b=%d, *c=%d; &a=%p, &b=%p, c=%p\n",
a, b, *c, (void *)&a, (void *)&b, (void *)c);

return 0;
}

ПРИМЕР ВЫХОДА:

a=10, b=100, *c=100; &a=0028FF18, &b=0028FF14, c=0028FF14
a=10, b=100, *c=10; &a=0028FF18, &b=0028FF14, c=0028FF18
a=10, b=100, *c=100500; &a=0028FF18, &b=0028FF14, c=0028FF18

СЛУЧАЙ 2 — МЫ НЕ ПЫТАЙТЕСЬ ЗАДАТЬ АДРЕС КОНСТА А:

#include <stdio.h>

int main ()
{
const int a = 10;
int b = 100;
int *c = &b;
printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
a, b, *c, (void *)&b, (void *)c);

c++;  // "c" now invalid
printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
a, b, *c, (void *)&b, (void *)c);

*c = 100500;  // Undefined behavior!
printf ("a=%d, b=%d, *c=%d; &b=%p, c=%p\n",
a, b, *c, (void *)&b, (void *)c);

return 0;
}

ОБРАЗЕЦ ВЫХОДА

a=10, b=100, *c=100; &b=0028FF14, c=0028FF14
a=10, b=100, *c=2686744; &b=0028FF14, c=0028FF18
a=10, b=100, *c=0; &b=0028FF14, c=00018894
0
По вопросам рекламы [email protected]