Подтвердить что ты не робот

Когда использовать const char * и когда использовать const char []

Я знаю, что они разные, я знаю, как они разные, и я читал все вопросы, которые я мог найти относительно char* vs char[]

Но все эти ответы никогда не говорят, когда они должны использоваться.

Итак, мой вопрос:

Когда вы используете

const char *text = "text";

и когда вы используете

const char text[] = "text";

Есть ли какое-либо правило или правило?

В качестве примера, какой из них лучше:

void withPointer()
{
    const char *sz = "hello";
    std::cout << sz << std::endl;
}

void withArray()
{
    const char sz[] = "hello";
    std::cout << sz << std::endl;
}

(Я знаю, что std::string также является опцией, но я специально хочу знать о char указателе/​​массиве)

4b9b3361

Ответ 1

Оба они совершенно разные, Для начала:

  • Первый создает указатель.
  • Второй создает массив.

Читайте дальше для более подробного объяснения:

Версия массива:

char text[] = "text"; 

Создает массив, который достаточно велик, чтобы содержать строковый литерал "текст", включая его терминатор NULL. Массив text инициализируется строковым литералом "text". Массив может быть изменен позднее. Кроме того, размер массива известен даже во время компиляции, поэтому для определения его размера можно использовать оператор sizeof.


Версия указателя:

char *text  = "text"; 

Создает указатель, указывающий на строковый литерал "text". Это быстрее, чем версия массива, , но строка, указанная указателем, не должна быть изменена, потому что она находится в определенной памяти только для чтения. Изменение такого строкового литерала приводит к Undefined Поведение.

На самом деле С++ 03 осуждает использование строкового литерала без ключевого слова const. Таким образом, декларация должна быть:

const char*text = "text";

Кроме того, вы должны использовать функцию strlen(), а не sizeof, чтобы найти размер строки, так как оператор sizeof просто даст вам размер переменной указателя.


Какая версия лучше?

Зависит от использования.

  • Если вам не нужно вносить какие-либо изменения в строку, используйте версию указателя.
  • Если вы намерены изменить данные, используйте версию массива.

РЕДАКТИРОВАТЬ: Мне просто было сообщено (в комментариях), что ОП ищет разницу между:

const char text[] и const char* text

Хорошо, что вышеупомянутые разные точки по-прежнему применяются, кроме тех, которые касаются изменения строкового литерала. С квалификатором const массив test теперь представляет собой массив, содержащий элементы типа const char, что означает, что они не могут быть изменены.

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

Ответ 2

Вероятно, самое большое различие заключается в том, что вы не можете использовать оператор sizeof с указателем, чтобы указать размер начального значения буфера, где, как и в версии const char[], вы можете использовать sizeof для переменной массива чтобы получить размер памяти в массиве в байтах. Так что это действительно зависит от того, что вы хотите делать с указателем или буфером, и как вы хотите его использовать.

Например, выполните:

void withPointer()
{
    const char *sz = "hello";
    std::cout << sizeof(sz) << std::endl;
}

void withArray()
{
    const char sz[] = "hello";
    std::cout << sizeof(sz) << std::endl;
}

даст вам очень разные ответы.

Ответ 3

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

В этом случае const char[] выигрывает, потому что содержит более подробную информацию о данных внутри - а именно, размер буфера.

Ответ 4

Просто примечание:

Я бы сделал это static const char sz[] = "hello";. Объявление как таковое имеет приятное преимущество в том, что внесение изменений в эту константную строку приводит к сбою программы путем записи в постоянную память. Без static отбрасывание константы, а затем изменение содержимого может остаться незамеченным.

Кроме того, static позволяет массиву просто лежать в секции константных данных вместо создания в стеке и копироваться из секции константных данных каждый раз, когда вызывается функция.

Ответ 5

Если вы используете массив, то данные инициализируются во время выполнения. Если вы используете указатель, накладные расходы времени выполнения (вероятно) меньше, потому что нужно инициализировать только указатель. (Если данные меньше, чем размер указателя, то инициализация данных во время выполнения меньше, чем инициализация указателя.) Итак, если у вас достаточно данных, которые имеют значение, и вы заботитесь о времени выполнения стоимость инициализации, вы должны использовать указатель. Вы почти никогда не будете заботиться об этих деталях.

Ответ 6

Мне много помогли блог-записи Ульриха Дреппера пару лет назад:

так близко, но без сигары и больше веселья в весе

Суть блога в том, что const char[] должен быть предпочтительным, но только как глобальная или статическая переменная.

Использование указателя const char* имеет следующие недостатки:

  • Дополнительная переменная
  • указатель доступен для записи
  • дополнительная ссылка
  • доступ к строке через указатель требует 2 загрузки памяти