По приведённой в вопросе ссылке описываются некоторые технические детали в работе компиляторов. С точки зрения стандарта языка расклад таков.
Все строковые литералы — это массивы со статическим классом памяти из n элементов, где n включает завершающий нулевой символ. Статический класс памяти означает, что массив существует на протяжении всего времени работы программы. Т.е. указатель на элемент строкового литерала можно, например, безопасно вернуть из функции.
const char* f1()
{
char arr[5] = {'t', 'e', 's', 't', '\0'};
//Возвращаем указатель на элемент локального массива.
//Массив перестаёт существовать при выходе из функции
//Поведение программы не определено.
return arr;
}
const char* f2()
{
//OK. "test" - статический массив, и он не будет уничтожен при выходе из функции
return "test";
}
Так как строковый литерал есть массив, то он может быть неявно приведён к указателю на свой первый элемент.
int arr_int[] = {48, 49, 50, 51, 0};
//OK. p_int указывает на первый элемент массива arr_int.
int* p_int = arr_int;
//OK p_char указывает на первый элемент массива "0123".
const char* p_char = "0123";
Тип элементов строкового литерала в языке C++ определяется следующим образом:
- Нет префикса —
const char,
- Префикс
u8 — const char8_t,
- Префикс
u — const char16_t,
- Префикс
U — const char32_t,
- Префикс
L — const wchar_t,
В языке C аналогично, но
- типы не содержат
const-квалификатора,
- тип элементов литералов с префиксом
u8 — char (в C11 так, возможно в последних версиях черновиков стандарта изменено),
- типы
char16_t и char32_t определены в заголовочном файле uchar.h и есть псевдонимы для типов uint_least16_t и uint_least32_t соответственно.
- тип
wchar_t определён в заголовочном файле stddef.h и есть псевдоним для некоторого другого целочисленного типа.
И в C, и в C++ попытка изменения строкового литерала приводит к неопределённому поведению.
Важное свойство строковых литералов — они могут перекрываться в памяти.
char arr1[] = {1, 2, 3};
char arr2[] = {1, 2, 3};
//Гарантированно false;
&arr1[0] == &arr2[0];
//Может быть как true, так и false.
&"test"[0] == &"test"[0];
В последнем примере можно было бы сравнить адреса первых элементов массивов arr1 и arr2 так:
arr1 == arr2
Это корректный код. Массивы неявно приводятся к указателям на свои первые элементы, и происходит сравнение указателей. Однако, в C++20 возможность сравнивать два операнда с типом массив признана устаревшей (deprecated), и, вероятно, будет удалена в будущих версиях стандарта языка.
int a[] = {1,2,3,4}- будет он точно так же сразу в образе программы. – Harry Feb 17 '21 at 08:16int * p = a;... – Harry Feb 17 '21 at 10:32