2016-04-15 3 views
2

Я знаю, что при использовании в качестве параметра функции char* a[] эквивалентно char a[][]. Использование char * a [] vs char a [] []

При использовании в качестве функционального параметра char* a[] эквивалентно char** a. Also known as Array to pointer conversion to some.

Однако при использовании в блоке сферы они не являются одинаковыми, и я запутался, когда я должен предпочесть один над другим, или если я должен пропустить char a[][], как я обычно склонны видеть char* a[] в других народный код.

Один аргумент против char a[][], очевидно, что вы должны указать фиксированный размер для C-строк, которые он будет содержать, но влияет ли это на производительность каким-либо образом?

Должен ли я предпочитаю это:

char* a[] = {"hello", "world"}; 

Или это:

char a[][10] = {"hello", "world"}; 
+1

Остерегайтесь любого предложения, которое начинается с «Я знаю это» ... –

+0

@KerrekSB Что значит? – hgiesel

+4

Ваше ведущее утверждение неверно. 'char a [] []' никогда не разрешается. Что эквивалентно, как типы параметров функции, это 'char * a []' и 'char ** a'. –

ответ

2

Настройка типа массива на тип указателя работает только в том случае, если он объявлен как параметр функции.
В качестве функционального параметра char* a[] будет скорректирован до char** a и char a[][10] до char (*a)[10]. В противном случае char* a[] объявляет a как массив указателей на char, а char a[][10] объявляет a массив массивов char.

Предпочтение

char* a[] = {"hello", "world"}; 

над этим

char a[][10] = {"hello", "world"}; 

имеет смысл, когда вы хотите сохранить несколько байт памяти. В последнем случае для каждого из a[0] и a[1] выделяется 10 байт. Обратите внимание, что в случае char* a[] строки, обозначенные элементами a, неизменяемы.

Если вы хотите смежное распределение памяти, перейдите по ссылке char a[][10].

+0

Вопрос OPs отличается от названия. – Michi

+0

В любом случае нет ничего, что можно было бы обсудить о 'Array of Arrays' (или multi dim) против' Array of Pointers', которые определенно разные. – Michi

+0

@Michi; Да. вот что я обратился в своем ответе. – haccks

8

Ключ к пониманию, казалось бы, странные случаи синтаксических параметров функции, чтобы понять распад массива. Это все о одном правиле в C, которое говорит: всякий раз, когда вы передаете массив как параметр функции, он распадается на указатель на первый элемент этого массива (*).

Так что, когда вы пишете что-то вроде

void func (int a[5]); 

затем во время компиляции, массив заменяется указателем на первый элемент, что делает выше равным:

void func (int* a); 

Это правило распада указателя рекурсивно применяется к многомерным массивам. Так что если вы передаете многомерный массив функции:

void func (int a[5][3]); 

он по-прежнему распадается на указатель на первый элемент. Теперь, когда это происходит, 2D-массив на самом деле представляет собой массив массивов. Поэтому первый элемент - это одномерный массив с размером 3 в этом примере. Вы получите указатель массива на этот массив, тип int(*)[3]. Заставить выше эквивалент

void func (int (*a)[3]); 

И это на самом деле причина, почему мы можем опустить крайний левый измерение параметра массива, а только то, что измерение. Поступая таким образом, мы создаем массив неполного типа, который вы обычно не сможете использовать: например, вы не можете писать код, например, int array[]; внутри тела функции. Но в случае с параметром не имеет значения, что самое левое измерение не указано, так как это измерение будет «распадаться» в любом случае.


(*) Источник, C11 6.7.6.3/7:

Объявление параметра как '' массив типа '' должен быть отрегулирован на '' квалифицированный указатель на тип» ', ...

+3

Разве это не * аргументы *, которые распадаются? Я уверен, что параметры настраиваются по типу. – juanchopanza

+1

@juanchopanza Умм ... аргумент и параметр - синонимы? – Lundin

+0

Утверждение о неполных типах немного расплывчато. * * Используется для неполных типов, например. вы можете использовать их в объявлениях: например, 'extern int a [];' отлично внутри функции. –

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