Строки C++: [] по сравнению с *

18
задан Johannes Schaub - litb 20 July 2010 в 10:48
поделиться

6 ответов

Давайте изучим его (для следующего, примечание char const и const char то же в C++):

Строковые литералы и символ *

"hello" массив 6 символов константы: char const[6]. Как каждый массив, это может преобразовать неявно в указатель на свой первый элемент: char const * s = "hello"; Для совместимости с кодом C, C++ позволяет еще одно преобразование, которое было бы иначе плохо сформировано: char * s = "hello"; это удаляет константу!. Это - исключение, для разрешения, что C-выход кодирует для компиляции, но он удерживается от использования для создания char * точка к строковому литералу. Таким образом, что мы имеем для [1 113]?

"foo"-> array-to-pointer-> char const*-> qualification-conversion-> char *. Строковый литерал только для чтения, и не будет выделен на стеке. Можно свободно заставить указатель указать им и возврату что один от функции, без [1 125] катастрофический отказ :).

Инициализация массива с помощью Строкового литерала

Теперь, что char s[] = "hello";? Это цело другая вещь. Это создаст массив символов и заполнит его Строкой "hello". На литерал не указывают. Вместо этого это копируется в символьный массив. И массив создается на стеке . Вы не можете законно возвратить указатель на него от функции.

типы Параметра массива.

, Как можно заставить функцию принять массив как параметр? Вы просто объявляете, что Ваш параметр массив:

void accept_array(char foo[]); 

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

void accept_array(char * foo);

Отклонение: Многомерные массивы

Замена char любым типом, включая выстраивает себя:

void accept_array(char foo[][10]);

принимает двухмерную антенную решетку, последний размер которой имеет размер 10. первый элемент многомерного массива является своим первым подмассивом следующего размера ! Теперь, давайте преобразуем его. Это будет указатель на свой первый элемент снова. Так, на самом деле это примет указатель на массив 10 символов: (удалите [] в голове и затем просто сделайте указатель на тип, который Вы видите в голове затем):

void accept_array(char (*foo)[10]);

, Поскольку массивы неявно преобразовывают в указатель на свой первый элемент, можно просто передать двухмерную антенную решетку в нем (чей последний размер размера равняется 10), и он будет работать. Действительно, это имеет место для [1 129] любой n-мерный массив, включая особый случай [1 123];

Заключение

void upperCaseString(char *_str) {}; 

и

void upperCaseString(char _str[]) {};

является тем же, поскольку первым является просто указатель для обугливания. Но отметьте, хотите ли Вы передать Строковый литерал тому (скажите, что он не изменяет свой аргумент), затем необходимо изменить параметр на [1 124], таким образом, Вы не делаете удержанных от использования вещей.

42
ответ дан 30 November 2019 в 06:12
поделиться

Три различных объявления позволяют указателю указать на различные сегменты памяти:

char* str = new char[100];

позволяет ул. указать на "кучу".

char str2[] = "Hi world!";

помещает строку на стек.

char* str3 = "Hi world!";

точки к сегменту данных.

Эти два объявления

void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};

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

12
ответ дан 30 November 2019 в 06:12
поделиться

Хорошо, я оставил два отрицательных комментария. Это не действительно полезно; я удалил их.

  • следующий код инициализирует символьный указатель, указывая на запуск динамично выделенной части памяти (в "куче".)

char *str = new char[100];

Этот блок может быть освобожден с помощью delete [].

  • следующий код создает массив символов в стеке, инициализированном к значению, указанному строковым литералом.

char [] str2 = "Hi world!";

Этот массив может быть изменен без проблем, который хорош. Так


str2[0] = 'N';
cout << str2;

должен распечатать Ni world! к стандартному выводу, делающие определенные рыцари чувствуют себя очень неловко.

  • следующий код создает символьный указатель в стеке, указывая строковый литерал ... Указатель может быть повторно присвоен без проблем, но резкий блок не может быть изменен (это - неопределенное поведение; это segfaults в соответствии с Linux, например.)

char *str = "Hi all";
str[0] = 'N'; // ERROR!
  • следующие два объявления

void upperCaseString(char *_str) {};
void upperCaseString(char [] _str) {};

выглядят одинаково мне , и в Вашем случае (Вы хотите к верхнему регистру строку на месте), это действительно не делает вопросов.

Однако все это вызывает вопрос: почему Вы используете char * для выражения строк в C++?

2
ответ дан 30 November 2019 в 06:12
поделиться

Также смотрите на http://c-faq.com/aryptr/aryptr2.html , C-FAQ мог бы оказаться интересным чтением сам по себе.

0
ответ дан 30 November 2019 в 06:12
поделиться

Как дополнение к ответам, уже данным, необходимо прочитать FAQ C относительно массивов по сравнению с указателями . Да это - FAQ C и не FAQ C++, но существует мало существенных различий между этими двумя языками в этой области.

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

0
ответ дан 30 November 2019 в 06:12
поделиться

Первая опция динамично выделяет 100 байтов.

вторая опция статически выделяет 10 байтов (9 для строки + nul символ).

Ваш третий пример не должен работать - Вы пытаетесь статически-заполнить динамический объект.

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

<час>

(Это - простой ответ - я ожидаю, что у кого-то еще будет авторитетный, сложный ответ из спецификации :))

-1
ответ дан 30 November 2019 в 06:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: