2010-04-09 4 views

ответ

0

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

Сложная часть вашего вопроса состоит в том, что даже если вы выделяете пространство для своей структуры, если ваша структура содержит указатель, вам нужно выделить ВТОРОЕ время для указателя, но сам указатель будет выделен как часть структуры allocaiton.

Если ваша структура содержит массив из 1, вам не нужно будет выделять какую-либо дополнительную память, она будет храниться в структуре (которую вы все еще должны выделить).

0

Это разные вещи.

Такое имя члена является адресом выделенной памяти, выделенной внутри самого экземпляра struct.

+1

Нет, это не «указатель на выделенную память». Это * выделенная память. Там нет «указателей». – AnT

+0

Но, как говорят Брайан У. Керниган и Деннис М. Ричи в своей книге «Язык программирования C»: «Объявление структуры, за которым не следует список переменных, не хранит никакого хранилища, а просто описывает шаблон или форму состав." Таким образом, у меня есть путаница в этом вопросе декларации и распределения памяти в определении структуры. Не могли бы вы объяснить это больше. спасибо – Walidix

2

Что вы описываете, это две разные вещи. Если у вас есть указатель в качестве члена:

a_struct_t* a_member; 

тогда это просто указатель. Внутри структуры не выделяется память для хранения a_struct_t. Если же, с другой стороны, у вас есть массив размером 1:

a_struct_t a_member[1]; 

тогда ваша структура на самом деле имеет объект типа a_struct_t внутри него. С точки зрения памяти, она не сильно отличается от просто поместить объект этого типа внутри структуры:

a_struct_t a_member; 

С точки зрения использования, массив требует косвенность для доступа к одному элементу (т.е. вам нужно используйте *a_member вместо a_member).

+0

Но, как говорят Брайан У. Керниган и Деннис М. Ричи в своей книге «Язык программирования C»: «Объявление структуры, за которым не следует список переменных, не сохраняет память, просто описывает шаблон или форму состав." Таким образом, у меня есть путаница в этом вопросе декларации и распределения памяти в определении структуры. – Walidix

+1

@Walidix: Это позволяет вам выполнять 'struct thing {...};' затем позже сказать 'struct thing aThing, someThings [thingCount];'. В любом случае интерпретация «struct thing» отличается от объявления элемента как массива или указателя. – dmckee

2

"Массив размера 1 вместо указателя"? Извините, но я не вижу, как это quiestion может иметь смысл. Я бы понял, если бы вы спросили о «массиве размера 1 вместо обычного члена (не-массива)». Но «вместо указателя»? С чем это связано? Как он взаимозаменяем с массивом, чтобы оправдать вопрос?

Если то, что вы действительно хотели, чтобы спросить, почему он объявлен как массив размера 1 вместо не-массив как в

struct { 
    a_struct_t a_member; 
} b_struct; 

затем один из возможных объяснений является хорошо известная идиома называется «структура хак ». Вы можете увидеть, как объявление

struct { 
    ... 
    a_struct_t a_member[1]; 
} b_struct; 

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

P.S. Время от времени вы можете увидеть «struct hack», реализованный через массив размером 0, что на самом деле является нарушением ограничения в C (то есть ошибкой компиляции).

+1

Структурный взлом часто используется при работе с пакетами обмена данными, где «полезная нагрузка» (или «остальная часть пакета») естественно встречается как последний член в структуре. –

+0

@ Кевин Маленький: И? – AnT

+0

Просто давая один конкретный пример того, где обычно используется структура переменной длины. Небольшой контекст реального мира помогает объяснить «выгоду» (использовать слова OP) структуры хака. –

5

В типичном случае структура с элементом, объявленным как массив одного элемента, будет иметь этот элемент как последний элемент в структуре. Цель состоит в том, что структура будет распределяться динамически.Когда он выделяется, то код будет выделить место для так много вещей, как вы действительно хотите/потребность в этом массиве:

struct X { 
    time_t birthday; 
    char name[1]; 
}; 

struct X *x = malloc(sizeof(*x) + 35); 
x->birthday = mktime(&t); 
strcpy(x->name, "no more than 35 characters"); 

Это особенно хорошо работает для строк - символ вы выделены в структуры дает вам пространство для терминатора NUL, поэтому, когда вы выполняете выделение, количество символов, которые вы выделяете, равно точно strlen() строки, которую вы собираетесь разместить там. Для большинства других видов предметов вы обычно хотите вычесть один из размера распределения (или просто жить с выделенным пространством, являющимся одним элементом больше, чем это строго необходимо).

Вы можете сделать (сорт) одно и то же с указателем, но это приведет к распределению тела структуры отдельно от элемента, на который вы ссылаетесь, с помощью указателя. Хорошим моментом является то, что (в отличие от вышеописанного метода) более чем один элемент может быть распределен динамически, причем вышеописанный метод работает только для последнего члена структуры.

+0

Самый новый стандарт C позволяет вам иметь имя символа []; в конце структуры, и gcc разрешил вам иметь имя char [0]; в конце структуры достаточно долгое время для этой цели. – nategoose

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