Я знаю, что это очень простой вопрос. Я смущен, почему и как отличаются друг от друга.
char str[] = "Test";
char *str = "Test";
Я знаю, что это очень простой вопрос. Я смущен, почему и как отличаются друг от друга.
char str[] = "Test";
char *str = "Test";
char str[] = "Test";
Является массивом chars
, инициализированным содержимым из "Test", а
char *str = "Test";
является указателем на строку литерала (const) "Test".
Основное различие между ними состоит в том, что первым является массив, а другой - указателем. Массив владеет своим содержимым, которое является копией "Test"
, в то время как указатель просто ссылается на содержимое строки (которая в этом случае является неизменной).
Указатель может быть перенаправлен на что-то еще:
char foo[] = "foo";
char bar[] = "bar";
char *str = foo; // str points to 'f'
str = bar; // Now str points to 'b'
++str; // Now str points to 'a'
Последний пример приращения указателя показывает, что вы можете легко перебирать содержимое строки, по одному элементу за раз.
Первый
char str[] = "Test";
представляет собой массив из пяти символов, инициализированный значением "Test"
плюс нулевой ограничитель '\0'
.
Второй
char *str = "Test";
- это указатель на ячейку памяти в литеральной строке "Test"
.
Один - это указатель, а один - массив. Это разные типы данных.
int main ()
{
char str1[] = "Test";
char *str2 = "Test";
cout << "sizeof array " << sizeof(str1) << endl;
cout << "sizeof pointer " << sizeof(str2) << endl;
}
Выход
sizeof array 5
sizeof pointer 4
Разница заключается в используемой памяти STACK.
Например, при программировании для микроконтроллеров, где выделено очень мало памяти для стека, имеет большое значение.
char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK
char *a = "string"; // the compiler puts just the pointer onto STACK
// and {'s','t','r','i','n','g',0} in static memory area.
Начиная с С++ 11, второе выражение теперь недопустимо и должно быть записано:
const char *str = "Test";
Соответствующим разделом стандарта является Приложение C, раздел 1.1:
Изменение: строковые литералы сделаны постоянными
Тип строкового литерала изменяется с "array of char" на "array of const char". Тип строкового литерала char16_t изменен с "массива типа с целым числом" на "массив константы char16_t". Тип строкового литерала char32_t изменен с "массива типа с целым числом" на "массив константы char32_t". Тип широкого строкового литерала изменяется с "array of wchar_t" на "array of const wchar_t".
Обоснование: это позволяет избежать вызова неуместной перегруженной функции, которая может ожидать изменения своего аргумента.
Влияние на исходную функцию: изменение семантики четко определенной функции.
"Test"
- массив из пяти символов (4 буквы, плюс нулевой ограничитель.
char str1[] = "Test";
создает этот массив из 5 символов и называет его str1
. Вы можете изменять содержимое этого массива столько, сколько хотите, например. str1[0] = 'B';
char *str2 = "Test";
создает этот массив из 5 символов, не называет его, а также создает указатель с именем str2
. Он устанавливает str2
, чтобы указать на этот массив из 5 символов. Вы можете следовать указателю, чтобы изменить массив столько, сколько хотите, например. str2[0] = 'B';
или *str2 = 'B';
. Вы даже можете переназначить этот указатель, чтобы указать где-то еще, например. str2 = "other";
.
Массив - это текст в кавычках. Указатель просто указывает на это. Вы можете делать много схожих вещей с каждым, но они разные:
char str_arr[] = "Test";
char *strp = "Test";
// modify
str_arr[0] = 'B'; // ok, str_arr is now "Best"
strp[0] = 'W'; // ok, strp now points at "West"
*strp = 'L'; // ok, strp now points at "Lest"
// point to another string
char another[] = "another string";
str_arr = another; // compilation error. you cannot reassign an array
strp = another; // ok, strp now points at "another string"
// size
std::cout << sizeof(str_arr) << '\n'; // prints 5, because str_arr is five bytes
std::cout << sizeof(strp) << '\n'; // prints 4, because strp is a pointer
для этой последней части, обратите внимание, что sizeof (strp) будет меняться в зависимости от архитектуры. На 32-битной машине это будет 4 байта, на 64-битной машине - 8 байтов.