Чтобы ответить на первый вопрос, принципы могут быть более ясными, если мы используем одну глубину указателя. Этот код является незаконным по той же причине:
int *ptr = { 1, 2, 3 };
В Си приготовилась список инициализатора не является объект (в частности, не массив).Его можно рассматривать только как список элементов, из которых следует читать инициализаторы, когда объект инициализируется.
ptr
- один объект, поэтому может быть выполнено не более одного инициализатора, и ожидаемая форма этого инициализатора является указателем (который не является 1
).
В самом деле этот код явно незаконным в соответствии с C11 6.7.9/11:
Инициализатор скаляр должно быть одно выражение, необязательно заключены в скобки
Однако существует gcc bug/feature, где он допускает избыточные инициализаторы для скаляра и игнорирует их. Кроме того, некоторые компиляторы могут «быть полезными» и «только» выдавать предупреждение и инициализировать ptr
, чтобы указать на адрес 1
, где бы это ни было.
«скаляр» означает объект, который не является структурой или массивом.
Так как C99 вы можете написать:
int *ptr = (int []){1, 2, 3};
, который создает массив (используя тот же срок хранения, как ptr
) и точек ptr
на его первый элемент.
Этот массив изменен; для неперемещаемого используйте вместо него int const *ptr = (int const[]){1, 2, 3};
.
Замена int
на char *
, мы видим, что вы могли бы написать:
char **p = (char *[]){ "123", "456", "789" };
в этом случае указатели в массиве изменчивы, но то, что они указывают на (то есть строковые литералы) все еще нет.
Обратите внимание, что при работе со строковыми литералами вы всегда должны использовать char const *
, потому что они не изменяемы. Тот факт, что строковые литералы имеют тип char [N]
исторический пережиток, прежде чем const
был добавлен в С. Итак:
char const **pp = (char const *[]){ "123", "456", "789" };
или с не изменяемых указателей на строки:
char const *const *pp = (char const *const []){ "123", "456", "789" };
я могу определить 'символ * * pp = {"123", "456", "789"}; '.. О ком компилятор мы говорим? –
Какова цель использования '++ (** pointerToPointer)'? – Subinoy
@EugeneSh. , С предупреждениями, хотя ... –