Почему мы не можем инициализировать двумерный целочисленный массив как указатель? - PullRequest
0 голосов
/ 18 декабря 2018

Почему двумерный массив символов можно инициализировать как указатель, но не как двумерный целочисленный массив?Почему выдает ошибку, когда я пытаюсь это сделать?Кроме того, что означает инициализация массива в качестве указателя?

#include<stdio.h>
int main()
{
    char* m[] = { "Excellent","Good", "bad" };
    int* x[] = { {1,2,3},{4,5,6} }; 
    return 0;                      
}

1 Ответ

0 голосов
/ 18 декабря 2018

В контексте объявления { и } просто означают «здесь есть группа вещей». Они не представляют объект, адрес или массив.(Примечание. Внутри инициализации есть выражения, и эти выражения могут содержать фигурные скобки в определенных контекстах, которые представляют объекты. Но в коде, показанном в вопросе, фигурные скобки просто группируют вещи.)

В char* m[] = { "Excellent","Good", "bad" }; перечислены три элемента для инициализации m: "Excellent", "Good" и "bad".Таким образом, каждый элемент инициализирует один элемент из m.

"Excellent" является строковым литералом.Во время компиляции он становится массивом символов, оканчивающихся нулевым символом.В некоторых ситуациях массив сохраняется как массив:

  • Когда он используется в качестве операнда sizeof.
  • Когда он используется в качестве операнда унарного & (для получения адреса).
  • Когда это строковый литерал, используемый для инициализации массива.

Ничто из этого не применимо в этой ситуации."Excellent" не является операндом sizeof, это не операнд &, и он инициализирует только один элемент m, а не весь массив.Таким образом, массив не сохраняется как массив: по правилу в C он автоматически преобразуется в указатель на свой первый элемент.Затем этот указатель инициализирует m[0]: m[0] является указателем на первый элемент "Excellent".

Аналогично, m[1] инициализируется указателем на первый элемент "Good", и m[2] инициализируется указателем на первый элемент "bad".

В int* x[] = { {1,2,3},{4,5,6} }; перечислены две вещи для инициализации x.Каждая из этих вещей сама является группой (из трех вещей).Однако x - это массив int *.Каждый элемент x должен быть инициализирован указателем.Но группа из трех вещей, {1,2,3}, не является указателем.

Правила Си для интерпретации групп вещей при инициализации массивов и структур немного сложны, потому что они предназначены для обеспечения некоторой гибкости при пропускефигурные скобки, поэтому я должен изучить стандарт немного больше, чтобы объяснить, как они применяются здесь.Достаточно сказать, что компилятор интерпретирует объявление как использование 1 для инициализации x[0].Поскольку 1 является int и x[0] является int *, компилятор жалуется, что типы не совпадают.

Дополнительные примечания

char *m[] не объявляетдвумерный массив.Это массив указателей на char.Из-за правил C, он обычно может использоваться синтаксически так же, как двумерный массив, так что m[i][j] выбирает символ j строки i.Однако существует разница между char *m[] и char a[3][4], например:

  • In m[i][j], m[i] - указатель.Этот указатель загружается из памяти и используется в качестве базового адреса для [j].Затем к этому адресу добавляется j, и символ загружается из памяти. В этой оценке есть две загрузки памяти.
  • В a[i][j], a[i] - массив.Местоположение этого массива вычисляется по арифметике от начала a.Тогда a[i][j] - это char, и его адрес вычисляется путем добавления j, и символ загружается из памяти. В этой оценке есть одна загрузка памяти.

Существует синтаксис для инициализации массива указателей int, указывающих на массив int.Он называется составной литерал .Это редко используется:

int *x[] = { (int []) {1, 2, 3}, (int []) {4, 5, 6} };

Ключевое различие между этими строковыми литералами и составными литералами состоит в том, что строковые литералы определяют объекты, которые существуют в течение времени выполнения программы, но составные литералы, используемые внутри функций, имеют длительность автоматического хранения- он исчезнет, ​​когда ваша функция вернется, и, возможно, раньше, в зависимости от того, где она используется.Программисты-новички С должны избегать использования составных литералов, пока не поймут правила продолжительности хранения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...