2013-08-08 3 views
3

, что будет размерность массива целых чисел обр, если объявлен как это:Декларация массива без самой высокой размерности

int arr[][2]={1,2,3}; 

что использование не объявляя самый высокий размер?

+1

Гибкость. Компилятор определяет размер в самом измерении, поэтому, если вы добавляете больше элементов, вам не нужно изменять константу в объявлении. (Но компилируется?) –

+0

Да (g ++, и gcc) – Jiminion

ответ

5

Несколько к моему удивлению, ваше заявление:

int arr[][2]={1,2,3}; 

, как представляется законным. Вы можете юридически опустить внутренние фигурные скобки в инициализаторах. Например, если вы хотите, чтобы определить границы arr явно и инициализировать все ее элементы, можно написать либо:

int arr[2][2] = { { 1, 2}, { 3, 4 } }; 

или, что то же самое:

int arr[2][2] = { 1, 2, 3, 4 }; 

Вы также можете опустить конечные элементы и они будут неявно установлены на ноль. Для одномерного массива это прямолинейно; это:

int arr[4] = { 1, 2, 3 }; 

эквивалентно:

int arr[4] = { 1, 2, 3, 0 }; 

И если опустить измерение, оно может быть выведено из инициализаторе:

int arr[] = { 1, 2, 3, 4 }; // 4 elements 

Поскольку вы определяете arr как массив из 2-элементных массивов int, это:

int arr[][2]={1,2,3}; 

эквивалентно следующему:

int arr[][2] = { { 1, 2 }, { 3 } }; 

У вас есть два элемента в инициализаторе (каждый из которых инициализируется массив 2-элемент), так что это эквивалентно:

int arr[2][2] = { { 1, 2 }, { 3 } }; 

Наконец, вы» ве опущен последней инициализации подэлемент, так что это неявно нулю:

int arr[2][2] = { { 1, 2 }, { 3, 0 } }; 

В общем, опуская размеры и конечные инициализаторы I полезно, потому что он позволяет компилятору выяснить некоторые вещи. Если я пишу:

char message[] = "hello, world"; 

Я не должен считать символы в строке (и добавить 1 для завершающего '\0'). Компьютеры действительно хороши в подсчете вещей; заставляя человека делать эту работу глупо.

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

struct foo obj = { .something = 42 }; 

As для выпрямления инициализаторов опуская внутренние фигурные скобки, я лично не вижу для этого используется много, за исключением специального случая использования инициализатора { 0 } для инициализации и полного массива или структуры до нуля.В частности, для многомерных массивов я нашел много clearer, чтобы показать всю структуру массива.

+0

Не правда. Последний элемент - хлам, в соответствии с gcc и g ++. – Jiminion

+1

@ Jim: У вас есть цитата для этого? В стандарте ISO C указано, что «все подобъекты, которые не инициализированы явно, должны быть инициализированы неявно так же, как и объекты , имеющие статическую продолжительность хранения», то есть до нуля. (Если нет инициализатора вообще, и объект определен в области блока, начальное значение - мусор.) –

+0

Ну, я построил рутину и протестировал ее. Это цитата? – Jiminion

1

согласно минимального брекетинга правила (6.7.9p20 в С11),

достаточно Инициализаторов из списка принимаются для учета элементов или членов subaggregate или первого члена содержащемуся союза ; любые оставшиеся инициализаторы оставляют для инициализации следующего элемента или члена совокупности, частью которого является текущий субагрегат или содержащий объединение.

Итак следующие объявления эквивалентны:

int arr[][2]={1,2,3}; 
int arr[][2]={{1,2},{3}}; 
int arr[2][2]={{1,2},{3}}; 

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

Смежные вопросы