Давайте изучим его (для следующего, примечание 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], таким образом, Вы не делаете удержанных от использования вещей.
Три различных объявления позволяют указателю указать на различные сегменты памяти:
char* str = new char[100];
позволяет ул. указать на "кучу".
char str2[] = "Hi world!";
помещает строку на стек.
char* str3 = "Hi world!";
точки к сегменту данных.
Эти два объявления
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
равны, компилятор жалуется на функцию, уже имеющую тело, когда Вы пытаетесь объявить их в том же объеме.
Хорошо, я оставил два отрицательных комментария. Это не действительно полезно; я удалил их.
char *str = new char[100];
Этот блок может быть освобожден с помощью delete []
.
char [] str2 = "Hi world!";
Этот массив может быть изменен без проблем, который хорош. Так
str2[0] = 'N';
cout << str2;
должен распечатать Ni world!
к стандартному выводу, делающие определенные рыцари чувствуют себя очень неловко.
char *str = "Hi all";
str[0] = 'N'; // ERROR!
void upperCaseString(char *_str) {};
void upperCaseString(char [] _str) {};
выглядят одинаково мне , и в Вашем случае (Вы хотите к верхнему регистру строку на месте), это действительно не делает вопросов.
Однако все это вызывает вопрос: почему Вы используете char *
для выражения строк в C++?
Также смотрите на http://c-faq.com/aryptr/aryptr2.html , C-FAQ мог бы оказаться интересным чтением сам по себе.
Как дополнение к ответам, уже данным, необходимо прочитать FAQ C относительно массивов по сравнению с указателями . Да это - FAQ C и не FAQ C++, но существует мало существенных различий между этими двумя языками в этой области.
кроме того, как примечание стороны, стараются не называть Ваши переменные с начальным символом подчеркивания. Это резервируется для символов, определенных компилятором и стандартной библиотекой.
Первая опция динамично выделяет 100 байтов.
вторая опция статически выделяет 10 байтов (9 для строки + nul символ).
Ваш третий пример не должен работать - Вы пытаетесь статически-заполнить динамический объект.
относительно upperCaseString()
вопрос, когда-то струна до была выделена и определена, можно выполнить итерации через нее или индексацией массива или нотацией указателя, потому что массив является действительно просто удобным способом перенести адресную арифметику с указателями в C.
(Это - простой ответ - я ожидаю, что у кого-то еще будет авторитетный, сложный ответ из спецификации :))