2016-02-02 2 views
-4

У меня есть метод, который возвращает void*, и это в основном некоторый блок данных из выделенной разделяемой памяти на linux.Извлечение int из void *

Первые 4 байта в этих данных: int, и мне не удалось извлечь этот int.

Это методы, что я пробовал:

int getNum(void* data) 
{ 
    return *(int*)data; // 1 
    return *(int*)(data & 0xFFFFFFFF); // 2 
} 

Заранее спасибо!

+0

Каково содержание данных? И что вы получаете? – frarugi87

+0

Содержимое - это int, а затем флаг, который является одним байтом ... Я получаю ошибку сегментации –

+0

В чем проблема? –

ответ

2
int getNum(void* data) 
{ 
    return *(int32_t*)data; // 1 
      // ^^^^^^^ 
} 

Должно работать.

Кроме того, если вам нужно беспокоиться о выровненных адресах, достигнутых с void*, вы можете использовать @Martin Bonner's suggestion:

int getNum(void* data) 
{ 
    int32_t result; 
    memcpy(&result, data, sizeof(int32_t)); 
    return result; 
} 
+0

Спасибо, я попробую это, как только я получу руки на рабочей станции. –

+0

Как это отличается от того, что в настоящее время используется? Modulo интегральный тип фиксированной ширины, т.е. –

+0

@Lightness Является ли 'int' гарантированностью 32 бита? Мне понравился момент Мартина Боннера о выровненном доступе. –

0

Предполагая Int имеет длину 4 байта, и вы работаете на Linux, ваш метод будет работать , Если вы хотите, чтобы переносимый метод перемещал ints в указателях, попробуйте модуль с открытым исходным кодом ptrint из CCAN. Он преобразует указатель на int, добавляя NULL к int. Он преобразуется в другом направлении, вычитая NULL, возвращая ptrdiff_t.

#include <assert.h> 
#include <stdio.h> 

int getNum(void* data) 
{ 
     return *(int *) data; 
} 

char buf[16]; 
int main(void) 
{ 
     assert(sizeof(int) == 4); 

     *(int *)buf = 9; 

     printf("%c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]); 

     printf("%d\n", getNum((void *) buf)); 

     return 0; 
} 

// $ ./foo | cat -tv 
// ^I^@^@^@ 
// 9 
+1

Добавление 'NULL' в' int' преобразует 'int' в указатель. Но это вряд ли переносится; арифметика указателя на нулевом указателе имеет неопределенное поведение. Если вам действительно нужно преобразовать указатели в целые числа или наоборот, используйте бросок.BTW, ваша функция 'getNum' такая же, как первый метод, показанный в вопросе, который OP уже сказал, не работал. –

+0

Да, но модуль ptrint запускает NULL, например: return (ptrint_t *) ((char *) NULL + i); Я знаю, что getNum идентичен OP - я пытаюсь продемонстрировать, что он работает **, и поэтому OP может иметь проблему в другом месте, например, когда значение первоначально записывается в память. – dancancode

1
int getNum(void* data) 
{ 
    return *(int*)data; // 1 
    return *(int*)(data & 0xFFFFFFFF); // 2 
} 

Второй метод не будет даже компиляции; data - это указатель, и вы не можете применить поразрядное устройство & к значению указателя. (Я не знаю, почему вы даже хотели бы скрыть значение указателя. Если это было законно, маска ничего не сделала бы в 32-битной системе и, вероятно, уничтожила бы значение указателя в 64-битной системе .)

что касается первых, он должен работать - если data является действительным указатель, указывающий на выровнены int объекта.

Если это терпит неудачу во время выполнения с ошибкой сегментации, это, вероятно, означает, что либо data является недействительным или иным образом не является допустимым указателем (в том случае, если вы не могут делать то, что вы пытаетесь сделать), или он указывает на несогласованный адрес (который не приведет к сбою seg, если вы находитесь в системе x86 или x86_64, не так ли?).

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

printf("data = %p\n", data); 

к вашей getNum функции - или проверить значение data в отладчике.

Если выравнивание является проблемой, то вы можете сделать это:

int result; 
memcpy(&result, data, sizeof result); 
return result; 

Но в этом случае, хранящем значение int в качестве смещенного адреса является нечетным, что нужно сделать в первую очередь. Это не обязательно неправильно, просто очень странная вещь.

Какова память, что data указывает на выделение?

+0

Маскирование, вероятно, предназначалось для применения к полученному значению, я подозреваю опечатку. –

+0

Помогло ли бы downvoter объяснить? –

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