2015-05-14 2 views
2
typedef struct node { 
    int value; 
    struct node* next; 
}node; 

int* to_array (node* ll, int size) { 
    int i = 0; 
    int* arr = malloc(size*sizeof(int)); 
    while (ll) { 
      arr[i] = ll->value; 
      ll = ll->next; 
      i++; 
    } 

return arr; 
} 

Может кто-то пожалуйста, объясните, почемуСтруктурированные связанный список в массив

int* arr = malloc(size); 

даст нам массив? Я подумал, что когда у нас есть указатели, мы не можем изменить его индивидуально, как arr[i] = 5 или что-то в этом роде.

ответ

5

На самом деле это очень хороший вопрос. Конечно, тот, о котором уже спрашивали и много раз отвечал на SO. Но, тем не менее, хороший вопрос.

С/FAQ C C++:

http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=aryptr

Массивы не являются указателями, хотя они тесно связаны между собой (см вопрос 6.3) и могут быть использованы аналогичным образом (см вопросы 4.1, 6.8, 6.10 и 6.14).

  1. Когда вы объявляете массив (например, int a[5]), вы выделили для хранения пяти элементов «ИНТ». Вы можете получить доступ к каждому элементу, например, a[i].

  2. Если вы указали указатель (например, int *b), вы не указали ЛЮБОЙ Хранение.

  3. Вы можете объявить и инициализировать указатель в то же время:

    int *b = NULL; /* Initialize to 0 */ 
    ... OR ... 
    int *b = malloc (5 * sizeof (int)); /* Allocate storage for 5 "int" elements */ 
    
  4. Когда вы объявили массив a, вы выделенное пространство из стека. Выделение не может быть изменено.

    Когда вы объявили b, вы выделили пространство SAME, но вы выделили его из кучи. Кроме того, вы можете изменить b, чтобы указать на что-нибудь еще, в любое время. Вы можете также realloc() свою память, чтобы изменить размер вашего хранилища.

  5. Как вы можете использовать индексный синтаксис a[i], вы используете точно такой же синтаксис b[i].

Эта ссылка может помочь объяснить: http://www.geeksforgeeks.org/g-fact-5/

PS: Когда вы "указателей", вы определенно CAN "изменить его по отдельности, как arr[i] = 5 или что-то".

+0

Спасибо. Я ценю ваше подробное объяснение! Я понимаю это сейчас. – wiwen

+0

Мое удовольствие. Спасибо * вы * :) – FoggyDay

2

int *arr = malloc(size * sizeof(int)); не дает массив, он дает вам блок памяти, достаточный для хранения целых чисел size.

arr[i] = ll->value; оператор использует арифметику указателей: выражение arr + 5 означает принимать адрес памяти целого числа указывает arr и переместить 5 позиций оттуда.Теперь, поскольку компилятор знает, что он работает с указателями int, и предположив, что 32-бит int s, он будет знать, чтобы добавить 20 (= 5 * 4 байта) в значение arr, чтобы найти 6-й элемент.

Далее, язык C имеет синтаксический сахар, где выражение arr[5] эквивалентно *(arr + 5).

Вот почему массивы в C индексируются из 0 и почему имя массива C также можно использовать в качестве указателя на первый элемент массива.

1

В этом утверждении

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

функция таНос выделяет степень памяти, которая способна хранить size объектов типа int и возвращает указатель в такой степени (или до первого временного интервала в той степени, где объект тип int может быть размещен) как имеющий тип void *, который неявно преобразован в тип int *, поскольку в левой части идентификатора декларации arr имеет тип int *.

Согласно стандарту C (6.5.2.1 индексация массивов)

2 ... Определение оператора индекса [] является то, что E1 [E2] является идентичными (* ((E1) + (E2))). Из-за правил преобразования, которые применяется к двоичному оператору +, если E1 является объектом массива (эквивалентно указателю на исходный элемент объекта массива) и E2 является целым числом, E1 [E2] обозначает E2- го элемента E1 (с нуля).

Таким образом, это выражение

arr[i] 

оценивается как

*(arr + i) 

где в подвыражению

arr + i 

там используется указатель арифметики, это выражение указывает на I -й элемент в выделенном ex палатка памяти.

Если у вас есть массив, объявленный, например, как

int array[size]; 

то в этом выражении

array[i] 

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

int *p = array; 
*(p + i) 

Таким образом, если у вас есть следующие объявления

int array[size]; 
int *p; 

то следующие утверждения эквивалентны

array[1] = 10; 

и

p = array; 

*(p + 1) = 10; 

Becuase операция array + i коммутативности, то вы можете написать взаимозаменяемые

array[i] 

и

i[array] 

Например, в вашей функции вы могли бы написать

i[arr] = ll->value; 

Хотя бы только запутать читателей. :)

Начинающие всегда удивляются, если посмотреть код, подобный этому

int a[10]; 

0[a] = 5; 
+0

Спасибо! Я понимаю это сейчас! – wiwen

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