Почему переменная-указатель char инициализируется в строку, но переменная-указатель int не может быть инициализирована массивом целых чисел?

Я пытаюсь понять взаимосвязь между строками, массивами и указателями.

В книге, которую я читаю, есть программа, в которой она инициализирует переменную следующим образом:

char* szString= "Name";

То, как я это понимаю, заключается в том, что строка в стиле C представляет собой просто массив символов. Массив - это просто сокращенная версия обращения к указателю (который сохраняет первое значение массива) и смещение. То есть array[5] фактически возвращает то, что оценивается из выражения *(array+5).

Итак, из моего понимания и тестирования szString фактически инициализируется как указатель, который указывает на первый адрес массива, хранящего "Имя". Я могу это сделать, потому что вывод:

cout << *szstring;

- символ "N".

Мое понимание утверждения

cout << szstring;

вывод символов "Имя" означает, что метод cout интерпретирует аргумент szstring как строковый тип и выводит все символы до символа NUL. С другой стороны, для аргумента *szstring используется другая версия этого метода, которая поддерживает строки в стиле C.

Поэтому, если я могу инициализировать указатель типа char для обращения к первому элементу в массиве символов (строка стиля C), почему я не могу инициализировать указатель типа int на первый элемент в массиве целые числа:

int* intArray = {1,2,3};

Ответ 1

строка в стиле C - это просто массив символов

Правильно.

Массив - это просто сокращенная версия обращения к указателю (который сохраняет первое значение массива) и смещение.

Нет, не совсем.

метод cout интерпретирует аргумент szstring как строковый тип и выводит все символы до символа NUL

cout не является "методом", но его operator<< работает так да.

Почему переменная-указатель char инициализируется в строке, но переменная-указатель int не может быть инициализирована массивом целых чисел?

Простой ответ заключается в том, что строковые литералы являются особыми, иначе мы не сможем их использовать.

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

почему я не могу инициализировать указатель типа int на первый элемент в массиве целых чисел

С++ мог бы в конечном итоге расширить синтаксис других инициализаций указателя, чтобы сделать аналогичную вещь, но на самом деле это не было нужно, потому что вместо этого у нас был намного выше:

std::vector<int> myInts{1,2,3};

Ответ 2

Короткий ответ заключается в том, что существуют литералы символьных массивов, но нет литералов int array.

Строковый литерал - это буквальное значение типа массива, и оно является lvalue, так что что-то, чей адрес вы можете взять и сохранить. Время жизни объекта, обозначенного таким значением, является постоянным, поэтому полученные таким образом указатели действительны на протяжении всей программы.

В отличие от этого, нет литерала типа "массив из int" и не имеет значения l-значений без имени int.

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

Во всяком случае, единственный нечетный пользователь в грамматике языка состоит в том, что допустимо инициализировать массив char с помощью скобочного списка, содержащего строковый литерал: char a[] = {"foo"}; Подумайте об этом как о своей инициализации; a - это копия литерала lvalue.

Ответ 3

В качестве новичков у меня был аналогичный вопрос. Пожалуйста, посмотрите этот пост и ответы.

Этот const char* szString= "Name" присваивает указателю szString адрес начального элемента массива, содержимое которого - "Имя" (за которым следует завершающий символ "\ 0" ).

Нет никакого неявного преобразования из int в int *, другое, что 0 является особым случаем, как нулевой указатель.