Как привести void * к int на 64-битных платформах, используя C? - PullRequest
1 голос
/ 28 февраля 2010

Я лингвист, отвечающий за программу на C, поэтому, пожалуйста, извините, если ответ очевиден У меня есть следующий код:

typedef struct array_s {
  (...)
  void **value;
} array_t;
typedef array_t *array_pt;

array_pt array_new (int size) {
  (...)
  array->value = (void **)malloc(size*sizeof(void *));
}

void* array_get (array_pt arr, int i) {
  return arr->value[i];
}

int main () {
  int a = 1234;
  int *ptr = &a;

  array_pt array = array_new(1);
  array_add(array, ptr);

  printf("%i\n", (int)array_get(array, 0));
}

Предполагается, что он предоставит мне многоцелевой массив (для хранения int и char*, если я понял, что могу использовать только void), и я думаю, что нет проблем с выделением / освобождением. Тем не менее, я не могу привести его к чему-либо полезному (то есть вернуть «оригинал» int / char *), и, как я понял, это может быть потому, что я нахожусь в 64-битной системе и размер указателя на void отличается от размера указателя на int / char* (программа должна использоваться как в 64, так и в 32 битных системах). Я попытался использовать intptr_t и другие альтернативы, но не повезло.

Как я могу быть уверен, что код примет любой тип данных и будет работать как в 32-, так и в 64-битных системах? Спасибо.

EDIT:

Извините, что не добавил array_add, вот оно:

unsigned int array_add (array_pt array, void *ptr) {
  (...) // get the next index
  // allocate if needed
  array->value = (void **)realloc(array->value, array->size*sizeof(void *));

  array->value[index] = p;
}

Ответы [ 3 ]

3 голосов
/ 28 февраля 2010

Вы должны решить, что именно вы пытаетесь сделать в этом случае.

(1) Если вы хотите использовать массив void * для хранения int значений ( фактическое int, принудительно преобразованное в void *)затем вы должны добавить эти int значения в массив следующим образом

int a = 1234; 

array_pt array = array_new(1); 
array_add(array, (void *) a); 

и затем получить их обратно из массива следующим образом

int a = (int) array_get(array, 0); 
printf ("%d\n", a);

или просто

printf ("%d\n", (int) array_get(array, 0)));

Эта последняя часть - именно то, что вы сделали, но вы ошиблись в первой части.

Это основанный на касте подход, который во многих отношениях безобразен, но имеет определенную практическую ценность и будетработа при условии, что void * достаточно велика, чтобы вместить int.Этот подход может зависеть от свойств 32- и 64-разрядных систем.

(2) Если вы хотите использовать массив void * для хранения значений int *(указывает на int), затем вы должны добавить эти int значения в массив следующим образом

int a = 1234; 

array_pt array = array_new(1); 
array_add(array, &a); 

и затем вернуть их из массива следующим образом

int *pa = array_get(array, 0); 
printf ("%d\n", *pa);

илипросто

printf ("%d\n", *(int *) array_get(array, 0));

Этот подход совершенно безопасен от любых проблем с переносимостью.У него нет 32- или 64-битных проблем.Указатель void * гарантированно надежно удерживает указатель int * или любой другой указатель данных.

Если это было вашим намерением, то вы правильно поняли первую часть, а последнюю - неправильно.

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

3 голосов
/ 28 февраля 2010

Вам нужно разыменовать ваш указатель:

int* temp = array_get(array, 0);
printf("%i\n", *temp);

Однако я настоятельно рекомендую избегать такого подхода. По сути, вы отказываетесь от небольшого количества помощи, которую обычно предоставляет компилятор в C, - целенаправленно пытаясь создать нетипичные массивы.

0 голосов
/ 28 февраля 2010

intmax_t должен быть целочисленным типом, 32-битным на 32-битных компиляторах и 64-битным на 64-битных компиляторах. Вы можете использовать% j в своем выражении printf для печати intmax_t. Размер указателей в одной системе всегда одинаков - независимо от того, указывают ли они на int, char или void.

printf("%j\n", (intmax_t)array_get(array, 0));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...