Приведение long int в качестве указателя на структуру - PullRequest
2 голосов
/ 12 декабря 2011

Я знаю, что это довольно бестолковый вопрос, но, похоже, не работает ни гугл, ни перестановки кода.

У меня есть структура, которая определяется следующим образом.

typedef struct
{
    int rate;
    int duration;
} DummyStructure;

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

//
DummyStructure* structure;
DummyStructure* structure2;
long int point;

//
structure = (DummyStructure*)malloc(sizeof(DummyStructure));
structure->rate = 19;
structure->duration = 92;
point = (long int)&structure;

// now i'd like to set structure2 to the same memory location as 1.
// point is the 8-byte int location (i assume?) of structure.
// so naturally i'd assume that by casting as a DummyStructure pointer
// that long int would act as a pointer to that 1.

// It doesn't.
structure2 = (DummyStructure*)point;

Я подчеркиваю, что я пробовал каждую перестановку ** и *, которая возможна.Я просто не понимаюЛибо это не компилируется, либо происходит, и когда это происходит, я получаю, казалось бы, случайные числа для полей, содержащихся в Structure2.Я предполагаю, что каким-то образом я получаю неправильное расположение в памяти, но как еще вы можете получить его, кроме как с помощью &?

У меня есть расположение в памяти, верно?Как установить структуру в это место?

РЕДАКТИРОВАТЬ;Я забыл упомянуть (и последующие ответы спросили), но я собираюсь использовать это, чтобы обернуть libvorbis для jni.Использование jni означает, что я не могу отменить ни одну из структур, которые выполняет libvorbis, но она требует их для своих основных функций.Поэтому моя обертка будет использовать vorbis напрямую для создания структур, и я возвращаю java указатель на них, чтобы, когда мне нужно было заполнить буфер большим количеством звука, я мог просто повторно ссылаться на объекты struct из целочисленного значения.указателя.

Ответы [ 7 ]

5 голосов
/ 12 декабря 2011

Почему вы пытаетесь привести указатели к целым числам и обратно? Это просто учиться, что-то придумывать, обходить какие-то (невыразимые) ограничения или как? Это довольно странно делать в такой простой программе, как эта, поскольку в этом нет никакого смысла.

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

printf("a regular pointer is %u bytes, long int is %u",
  (unsigned int) sizeof structure, (unsigned int) sizeof point);

Если напечатанные цифры отличаются, это, вероятно, самая большая причина ваших проблем.

Если вы используете C99, вы должны #include <stdint.h> и затем использовать тип intptr_t вместо unsigned long для удержания указателя в любом случае.

4 голосов
/ 12 декабря 2011

structure уже является указателем, поэтому вам не нужно указывать там адрес:

long int point = reinterpret_cast<long int>(structure);
DummyStructure* structure2 = reinterpret_cast<DummyStructure*>(point);
3 голосов
/ 12 декабря 2011

Другие ответили на ваш вопрос, но я хотел бы сделать более общий комментарий. Вы упоминаете JNI; в этом случае вы не хотите long int, но jlong (который будет typedef или long int или long long int, в зависимости от машины. Проблема в том, что long будет иметь другой размер , в зависимости от машины, и будет отображаться на другой тип Java. Конечно, вы рассчитываете на то, что jlong будет достаточно большим, чтобы содержать указатель, но, поскольку jlong - это 64-битная версия, это выглядит как безопасная ставка на ближайшее будущее (и за ее пределами - я не вижу времени, когда 64-битной адресации недостаточно).

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

jlong forJNI = 0;
*reinterpret_cast<DummyStructure*>( &forJNI ) = structure;
//  ...
structure2 = *reinterpret_cast<DummyStructure*>( &forJNI );

Это безобразно, но гарантированно работает (с одним предупреждением) для всех системы где sizeof(DummyStructure*) <= 64.

Только обязательно скомпилируйте с выключенным строгим псевдонимом. (Ты должен делайте это каждый раз, когда вы разыгрываете указатели и целые числа. ИМХО, не стоит приходится в случаях, когда приведенные значения видны компилятору, но некоторые авторы компиляторов предпочитают намеренно нарушать код, даже если намерение ясно.)

3 голосов
/ 12 декабря 2011

structure уже указатель.Вы просто хотите сделать point = (long int) structure; (хотя, на самом деле, почему вообще используется long int, я не знаю. Намного проще просто сделать structure2=structure;, который отлично работает, так как structure и structure2оба указателя.)

Когда вы делаете &structure, вы получаете место в памяти, где хранится сам указатель, поэтому это неверное значение.Вы действительно, вероятно, не захотите когда-либо использовать &structure, если он не передан в функцию, которая собирается изменить то, на что указывает DummyStructure structure.

1 голос
/ 12 декабря 2011

Длинные целые не совпадают с указателями.Почему бы вам просто не сделать:

DummyStructure** point;

structure = malloc(sizeof(DummyStructure));
structure->rate = 19;
structure->duration = 92;
point = &structure;

structure2 = *point;

Возможно, проблема в том, что 1) у вас нет точки разыменования.structure2 - это указатель на structure, который сам является указателем.Вам нужно будет сделать:

structure2 = *((DummyStructure*)point);

Но вдобавок ко всему это тот факт, что длинные целые числа не совпадают с указателями.Возможно, здесь также есть проблема подписи.

0 голосов
/ 12 декабря 2011

Ошибка в том, что point - это адрес structure, который сам по себе является указателем на DummyStructure. Чтобы structure2 указывал на то же самое, что и structure, вам нужно разыменовать point. Игнорирование на секунду всей длины, подписи и подобных проблем,

structure2 = *(DummyStructure**)point;

исправит ваш код. Но почему бы просто:

structure2 = structure;

Если вы действительно хотите держать указатель в чем-то общем, удерживайте его в void*. По крайней мере, это правильный размер.

0 голосов
/ 12 декабря 2011
point = (long int)&structure;

Он принимает адрес structure, который является DummyStructure*, и присваивает его point. Так что point должен быть двойным указателем (указатель на указатель). И когда вы назначаете structure2, он должен быть правильно приведен к типу.

typedef struct
{
    int rate;
    int duration;
} DummyStructure;

DummyStructure* structure;
DummyStructure* structure2;
long int **point;
structure = (DummyStructure*)malloc(sizeof(DummyStructure));
structure->rate = 19;
structure->duration = 92;
point = (long int **)&structure;
structure2 = (DummyStructure*)*point;

Если вы хотите, чтобы structure2 указывал на ту же ячейку памяти, что и structure, почему бы вам не назначить его напрямую вместо промежуточного long int **.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...