В чем разница между этими двумя определениями буквальных строк ?:

const char *message1 = "message1";
const char message2[] = "message2";

Если оба они заканчиваются нулем, это так странно - когда я передаю первый в какую-то функцию печати текста, я получаю ошибку «память не может быть записана», но когда я передаю второй, все в порядке !?

enter image description here

Функция вопроса - это некая сторонняя функция из источника мода игры Fallout 2 под названием sfall . Насколько мне известно, эта функция вызывает встроенную функцию, определенную движком Fallout 2, которую код sfall вызывает с помощью собственной оболочки.

1
Daros911 8 Июн 2021 в 20:25

3 ответа

Лучший ответ
const char message2[] = "message2";

"message2" будет помещен в постоянную память. Затем его символы копируются в выделенную память массива message2[].

const char *message1 = "message1";

"message1" будет помещен в постоянную память. message1 будет просто указателем на эту память.

В обоих примерах значения являются постоянными .

2
Remy Lebeau 8 Июн 2021 в 17:43

В первом случае строковый литерал распадается на указатель.

Во втором случае строковый литерал сохраняется в массиве символов, размер которого компилятор автоматически подбирает так, чтобы он соответствовал литералу с нулевым терминатором.

Со вторым вы сохраняете больше информации в своей переменной. Так, например, вы можете позвонить std::size по второму, но не по первому.

Вызов функции печати, которая принимает const char*, должен быть одинаковым в обоих случаях. Поскольку во втором случае const char[] распадется на указатель в момент вызова функции.

2
user4581301 8 Июн 2021 в 19:18

В чем разница между этими двумя определениями буквальных строк?

message1 - указатель на строковый литерал.

message2 - это копия строкового литерала в виде массива.

Рассмотрим гипотетическую враждебную функцию печати.

void hostile_print( const char* msg )
{
    const_cast<char*>(msg)[0] = 0;
}

В приведенном ниже коде адрес этого строкового литерала мог находиться в памяти, которая была помечена ОС как доступная только для чтения. Это не редкость для строковых литералов.

Несмотря на это, hostile_print фиксирует Неопределенное поведение , и ОС выдает вам это сердитое диалоговое окно. Потому что Undefined Behavior может выглядеть так.

const char *message1 = "message1";
hostile_print(message1);

В приведенном ниже коде адрес массива может находиться в памяти, которую ОС пометила как доступную для записи. Возможно стек. Это не редкость для локальных массивов.

В любом случае hostile_print фиксирует Неопределенное поведение , и программа работает, как ожидалось. Потому что Undefined Behavior может выглядеть так.

const char message2[] = "message2";
hostile_print(message2);

В любом случае функция записывает в память то, чего не должна.

0
Drew Dormann 8 Июн 2021 в 19:31