Давайте разберемся с ним (обратите внимание, что char const
и const char
одинаковы в C ++):
Строковые литералы и символы *
"hello"
- это массив из 6 константных символов: char const[6]
. Как и любой массив, он может неявно преобразовывать указатель на свой первый элемент: char const * s = "hello";
Для совместимости с кодом C, C ++ допускает еще одно преобразование, которое в противном случае было бы некорректным: char * s = "hello";
удаляет const !. Это исключение, позволяющее компилировать этот C-ish-код, но не рекомендуется указывать char *
на строковый литерал. Итак, что мы имеем для char * s = "foo";
?
"foo"
-> array-to-pointer
-> char const*
-> qualification-conversion
-> char *
. Строковый литерал доступен только для чтения и не будет размещен в стеке. Вы можете свободно указать на них указатель и вернуть его из функции, без сбоя :).
Инициализация массива с использованием строкового литерала
Теперь, что такое 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), и он будет работать. Действительно, это относится к любому n-мерному массиву, включая особый случай n = 1
;
Заключение
void upperCaseString(char *_str) {};
и
void upperCaseString(char _str[]) {};
такие же, как первый - просто указатель на символ. Но учтите, что если вы хотите передать ему строковый литерал (скажем, он не меняет свой аргумент), то вы должны изменить параметр на char const* _str
, чтобы не делать устаревшие вещи.