Member 13798855 Ответов: 6

Проблема с 64 битным он дает неправильное значение


typedef struct _tagStrRec {
	short		nSym;					// string numeric ID
	short		nSec;					// area numeric ID
	short		nLen;					// string len
	long		lSeek;				// seek position within the file
} PSTRTBL, FAR* LPPSTRTBL;



PSTRTBL strTbl;
strTbl.nSym = 20;
strTbl.nSec = 50;

LPPSTRTBL pStrTbl = &strTbl;
pStrTbl->lSeek = 0;
pStrTbl->nLen = 20;
pStrTbl->nSec = 10;
pStrTbl->nSym = 20;

PSTRTBL strTbl1;
strTbl.nSym = 100;
strTbl.nSec = 800;

LPPSTRTBL pStrTbl1 = &strTbl1;
pStrTbl1->lSeek = 30;
pStrTbl1->nLen = 50;
pStrTbl1->nSec = 60;
pStrTbl1->nSym = 80;

long lInd = HandleToLong(pStrTbl) - HandleToLong(pStrTbl1);


Что я уже пробовал:

Я конвертирую свое приложение из 32-битного в 64-битное в 32-битном значении lInd = 32, но в 64-битном оно приближается к -80.

Линд долго = (долго)(pStrTbl) - (длинные)(pStrTbl1); //32 бита
long lInd = HandleToLong(pStrTbl) - HandleToLong(pStrTbl1); //64bit

Не могли бы вы сообщить мне об этом вопросе?

Member 13798855

Линд для 32 - битного и 64-битного отличается , я не уверен, почему ?

6 Ответов

Рейтинг:
1

Patrice T

Цитата:
Не могли бы вы сообщить мне об этом вопросе?

Возможно, проблема заключается в ваших ожиданиях относительно того, как и где структуры распределяются в памяти.
Нет сомнения, что существуют различия между 32 битами и 64 битами.
long lInd = (long)(pStrTbl) - (long)(pStrTbl1); //32 bit
long lInd = HandleToLong(pStrTbl) - HandleToLong(pStrTbl1); //64bit

выведите значения указателей, используемых в вашем расчете, и посмотрите, что есть что.


Рейтинг:
1

Richard MacCutchan

Я получаю другой ответ, но не совсем ясно, что именно вы пытаетесь сделать. У вас есть две предварительно выделенные структуры strTbl и strTbl1 Вы устанавливаете некоторые значения в этих структурах. Затем вы создаете указатели на эти две структуры и устанавливаете в них несколько различных значений. Затем вы вычисляете разницу между их адресами.

Вам нужно объяснить, что вы подразумеваете под "неправильным значением". я проверил, и все значения верны.


Member 13798855

это на самом деле пример кода, который я пытался сделать ..значение lIndx отличается для 32 - битного и 64-битного BI. Не могли бы вы сообщить мне об этом вопросе?

Richard MacCutchan

Ну, это пример кода, который не служит никакой полезной цели и ничего не доказывает. Когда вы создаете переменную в стеке или куче, ей выделяется место в любой свободной части памяти. Таким образом, адреса ваших структур могут быть любыми случайными значениями, которые не имеют никакого отношения друг к другу. Если вы хотите получить истинное сравнение между 32 и 64 битами, то сделайте что-то вроде этого:

PSTRTBL strTbls[2];
long diff = &strTbls[1] - &strTbls[0];

Но результат будет не таким, как вы думаете.

Member 13798855

long lInd отличается для обеих конфигураций

Рейтинг:
1

OriginalGriff

HandleToLong берет дескриптор и возвращает длинное значение, на которое ссылается дескриптор. Вы передаете адрес памяти (который может быть в стеке, а может и нет - зависит от вашего кода) и ожидаете ... Я не знаю, что именно.

Дескриптор может быть указателем - он объявлен таковым в файле .h - но это не значит, что указатель является дескриптором!

Даже если вы вычтете два указателя, результат не будет полезным или даже согласованным между компиляторами. Нет никакой гарантии, что память выделяется "сверху вниз" при компиляции вашего приложения; это внутренняя функция компилятора, и на нее не следует полагаться, чтобы дать вам какое-либо указание на "интервал" между данными в физической памяти.
Вычитание адресов памяти подобно сложению телефонных номеров: вы не получаете ничего особенно полезного!

И помните: в 64-битных приложениях указатели-это 64-битные значения. Рассматривая их как дескриптор и пытаясь преобразовать их в 32-битные и ожидая, что он будет работать точно так же, как и раньше, на самом деле не будет работать...


Member 13798855

спасибо

Рейтинг:
0

KarstenK

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

Сравнение дат производится следующим образом:

long seeked = pStrTbl1->lSeek - pStrTbl->lSeek;


Рейтинг:
0

steveb

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

И кстати, ваш код, похоже, нацелен на 16-битную систему, используя FAR*, который не нужен на 64-битной системе


Рейтинг:
0

Rick York

Вы должны использовать тип INT_PTR для lInd. Он автоматически настраивается под размер слова, которое вы используете. Тип long по-прежнему является 32-битным в 64-битном мире, поэтому он не подходит для работы с 64-битными указателями.

Кроме того, с тех пор как Win32 был впервые выпущен, нет никакой необходимости или ценности в том, чтобы что-то было далеко. С тех пор это абсолютно ничего не значило, так что сделайте себе одолжение и избавьтесь от него. В то время как вы занимаетесь этим, Вы должны потерять префикс L на указателях также потому, что нет никакого различия для длинных указателей, так как они по существу то же самое, что и FAR.