Инициализация непостоянной статической строки с помощью constexpr

Верен ли следующий код?

constexpr char s[] = "a, bb, ccc";
static const char * s1 = s;
char * s2 = const_cast<char *>(s1);
s2[5] = 'x';

Моя первая идея заключалась в том, что 's' существует только во время компиляции, а 's1', вероятно, является какой-то копией 's', но, вероятно, это не совсем правильно, потому что строка 2 не компилируется без 'const':

static char * s1 = s;

Ошибка с MSCV2017: «инициализация»: невозможно преобразовать «const char [11]» в «char [11]».

поэтому непонятно, какая связь между «s» и «s1»? Ссылаются ли они на один и тот же строковый литерал?

Обратите внимание, что тег c++17 относится к C++17 стандартный, а не к MSVC2017 (это будет тег visual-studio-2017).

Some programmer dude 08.04.2019 13:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
160
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Определение

static const char * s1 = s;

равно

static const char * s1 = &s[0];

То есть вы заставляете s1 указывать на первый элемент s, вот и все. Никакой "копии" не делается.

Вот почему вы не можете использовать указатели на неконстантные (т.е. char *), поскольку s1 будет указывать на постоянные данные.

И именно поэтому s2[5] = 'x' приведет к неопределенное поведение, когда вы попытаетесь изменить постоянные данные.

приводит ли этот код к неопределенному поведению: {const int a = 1; const_cast<int *>(&a) = 5;} ?

Alexey Starinsky 08.04.2019 14:02

@AlexeyStarinsky Даже не компилируется error: lvalue required as left operand of assignment

Tetix 08.04.2019 14:05

@Tetix OP пропустил разыменование или OP мог использовать ссылку напрямую, но дело в том, что вы не можете изменить a.

Acorn 08.04.2019 14:06

@Tetix Я имею в виду {const int a = 1; *(const_cast<int *>(&a)) = 5;}

Alexey Starinsky 08.04.2019 14:07

@AlexeyStarinsky Да, это UB. Любая попытка изменить постоянные данные приводит к UB.

Some programmer dude 08.04.2019 14:08

@Acorn, для чего нужен const_cast?

Alexey Starinsky 08.04.2019 14:08

@Someprogrammerdude, для чего нужен const_cast?

Alexey Starinsky 08.04.2019 14:09

@AlexeyStarinsky Любое использование const_cast должно быть красным флагом, что происходит что-то плохое. Как и старые слепки в стиле C.

Some programmer dude 08.04.2019 14:09

@AlexeyStarinsky Вы не можете отбрасывать const, используя другие примитивы приведения C++, только используя const_cast. Но, как я сказал выше, не делайте этого.

Some programmer dude 08.04.2019 14:10

@alexey, если у вас есть указатель на const или ссылка на const, а также вы знаете, что данные на самом деле не являются константами, приведение const позволяет безопасно их отбрасывать. Если вы ошибаетесь, это УБ. Вы также можете добавить const с помощью const cast.

Yakk - Adam Nevraumont 08.04.2019 14:23

my first idea was that 's' exists only at compile time

Нет, он также существует во время выполнения. constexpr не означает «только во время компиляции». Здесь это означает, что «s должен быть инициализирован константным выражением» (по сути, константой времени компиляции), что означает, что его можно использовать и в константных выражениях.

's1' probably is some kind of a copy of 's'

s1 просто указывает на первый символ массива s. Это не копия содержимого массива.

line 2 does not compile without 'const':

Вы не можете сделать это без const_cast -- но в любом случае вам это не нужно, потому что изменение исходной const переменной (которой является s) является неопределенным поведением.

Другие вопросы по теме