Объявление массива в c

Возможный дубликат:
переменные стека и переменные кучи

В чем разница между объявлением массива как:

int arr[100];

а также

int* arr=(int*)malloc(sizeof(int)*100);

Какой из них предпочтительнее? Есть ли в этом что-то вроде памяти кучи и стека?


person Divij    schedule 14.07.2011    source источник
comment
@JSBangs: Да, переменные стека и переменные кучи точно отвечают на мой вопрос. Спасибо, что направили меня туда.   -  person Divij    schedule 14.07.2011


Ответы (3)


Я предлагаю сходить в книжный магазин, чтобы купить книгу Кернигана и Ритчи Язык программирования C и, при желании, книгу C: Справочное руководство от Harbison & Steele.

Первый случай дает вам массив из 100 целых чисел, выделенных в стеке. В последнем случае вы получаете указатель на целое число, адрес которого совпадает с адресом буфера, выделенного в куче, размер которого достаточно велик, чтобы вместить 100 целых чисел.

Язык C по своей сути является аппаратно-независимым языком ассемблера. Различие между указателем и массивом намеренно размыто, поскольку нотация ссылки на массив является синтаксическим сахаром для арифметики указателя. Этот:

int foo( int a )
{
  int x[100] = load_X() ;
  int y = x[ a ] ;
  return y ;
}

идентичен

int foo( int a )
{
  int *x     = load_X() ;
  int y      = *( x + a ) ;
  // note that the use of sizeof() isn't required.  For the pointer carries around
  // an implicit increment size (the size of the object to which it points). The above
  // is equivalent to
  //
  //   int y = *(int*)((char*)x + (a*sizeof(*x)) ) ;
}

Далее компилятор будет (или должен) ныть о несоответствии типов, учитывая функцию foo():

public void foo( int a[] )
{
  ...
}

Вызов:

int *p = malloc(...) ;

foo(p) ;

должно привести к жалобам компилятора на несоответствие типов.

person Nicholas Carey    schedule 14.07.2011

Первый объявляет arr как массив типа int[100], который находится в стеке. В некоторых контекстах arr будет распадаться на указатель типа int *, но это не делает его указателем. Чтобы еще больше подчеркнуть, что это не указатель, sizeof(arr) даст sizeof(int) * 100, а не размер адреса.

Второй объявляет указатель типа int * и инициализирует его указателем, возвращаемым malloc, который фактически выделяет память в куче. Обратите внимание, что в данном случае arr не является массивом — вы можете использовать нотацию массива для смещения и разыменования указателя, но это не делает его массивом.

person Blagovest Buyukliev    schedule 14.07.2011

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

Последний выделяет место для 100 ints в свободной памяти и возвращает указатель на начало блока памяти. Он останется выделенным до тех пор, пока для указателя не будет вызвана функция free().

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

person dlev    schedule 14.07.2011