2013-04-20 1 views
2

У меня есть массив пустоты-указатели и хочу получить доступ к элементам (inititialize их), но это не работает:Указателя пустого массива

void* anyptr = ...; //a pointer to something 
void* arr = (void*)malloc(sizeof(void*)*10); 

int i=0; 
for(i=0; i<10; i++) 
    *(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too 

Я думаю, причина, почему это won't работа что в левой части есть результат элемента i. Но у меня нет идеи, как это сделать

+5

Почему вы используете 'void *' для 'void *'? [Вы никогда не должны бросать его в любом случае.] (Http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – 2013-04-20 19:08:18

+0

'* (arr + i)' разыменовывание указателей void. – BLUEPIXY

ответ

14

Есть два способа инициализации массивов в C:

  • На стек (который будет обрабатывать память для вас, так как он будет очищен, когда ваша функция заканчивается)
  • В куче (что потребует от вас управления и выделения самостоятельно).

Если вы хотели бы использовать стек, вы можете инициализировать массив как это ...

#define ARRAY_LENGTH 10 
void *ptr; 
void *arr[ARRAY_LENGTH]; 
for (int i = 0; i < ARRAY_LENGTH; i++) { 
    arr[i] = ptr; 
} 

Аналогичным образом можно определить ваш массив в куче, как следует ...

#define ARRAY_LENGTH 10 
void *ptr; 
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH); 
for (int i = 0; i < ARRAY_LENGTH; i++) { 
    arr[i] = ptr; 
} 
free(arr); 

Важно помнить, что массив (помимо массивов, назначенных в стеке, которые имеют некоторые дополнительные атрибуты, такие как длина), по существу, является просто указателем на первый элемент, а операция arr [i] - это то же самое, что перемещение i * sizeof (elem) байт вдали от первого элемента и доступ к памяти там. Если вы хотели бы получить указатель на я го индекса в массиве, то вы должны использовать обозначение, такие как ...

void *indexPtr = arr + i; 

или

void *indexPtr = &(arr[i]); 

В этой моде, массив от void * 's будет иметь тип void **, так как переменная является указателем на первый элемент массива, который является указателем.Это может быть немного запутанным, но всегда старайтесь иметь в виду, какой тип элементов массива, и создавать указатель на них. Таким образом, если массив имеет тип INT, то массив будет иметь тип INT или ИНТ [], но если вы хранения указателей на целые числа, вы бы инициализировать массив типа Int * в любом из этих двух форм ...

int **arr = malloc(sizeof(int *) * ARRAY_LENGTH); 
int *arr[ARRAY_LENGTH]; 

Также обратите внимание, что вы храните указатели, так что если вы запустите код ...

int *arr[4]; 
for (int i = 0; i < ARRAY_LENGTH; i++) { 
    arr[i] = &i; 
} 

Хотя это может показаться, что значения указали в массив будет таким, как lows- [0, 1, 2, 3], но на самом деле это было бы [4, 4, 4, 4], поскольку у вас на самом деле есть массив указателей, указывающих на переменную i в вашей функции, поэтому всякий раз, когда вы меняете это, значения, указанные в массиве, будут изменены.
Я надеюсь, что это помогло

8

Вы должны изменить эту линию

void* arr = (void*)malloc(sizeof(void*)*10); 

к этому

void** arr = malloc(sizeof(void*)*10); 
+0

Не могли бы вы объяснить, почему он объявлен как указатель на указатель? – init

+1

@init, потому что это то, что вы выделяете для памяти: 10 указателей. Как вы указываете на эту память? Вы указываете на первый указатель. Следовательно, это указатель на указатель. Вы добавляете 1 к нему, и вы указываете на следующий указатель и так далее до последнего из 10 указателей. –

1

вы не можете разыменования указателя ничтожной. В этом весь смысл указателей пустоты. Выделение указателя дает вам доступ к элементу, найденному по адресу, на который указывает указатель. Однако с указателем void вы не знаете, насколько велик целевой объект (это 1B-символ или 100B-структура?). Перед разыменованием его нужно передать его конкретному типу указателя.

Добавление (или вычитание) целого числа i указателю затем определяется как добавление i-times sizeof (* указатель) к содержимому указателя. (Вы можете указывать только указатель sizeof (* указатель), если ваш указатель имеет определенный тип. Арифметика указателя с указателями void не имеет смысла).

Что касается (arr + n) = anyptr ;, arr + n - это всего лишь адрес. Это не значение, которое вы можете присвоить (а не lvalue).

+0

и как я могу изменить значение на адрес arr + n? – 0xDEADBEEF

+0

Отбрасывая его на определенный тип указателя, а затем разыгрывая его. Обратите внимание, однако, что ptr + n, если ptr является непустым указателем, будет означать n элементов впереди ptr, что не обязательно означает n байтов (это делается для указателей char *, но для указателей int это, скорее всего, означает n * 4 байта вперед, а для указателей на указатели (любого типа) это будет означать 4 * n или 8 * n в зависимости от вашей архитектуры (32 или 64 бит соответственно). – PSkocik

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

  • Нет связанных вопросов^_^