Разница между дальним и огромным указателями:
Как мы знаем по умолчанию, указатели near
, например: int *p
- это указатель near
. Размер указателя near
составляет 2 байта в случае 16-битного компилятора. И мы уже хорошо знаем, что размер компилятора варьируется; они хранят только смещение адреса, на который ссылается указатель. Адрес, состоящий только из смещения, имеет диапазон от 0 до 64 Кбайт.
Far
и huge
указатели:
Указатели
Far
и huge
имеют размер 4 байта. Они хранят как сегмент, так и смещение адреса, на который ссылается указатель. Тогда в чем разница между ними?
Ограничение дальнего указателя:
Мы не можем изменить или изменить адрес сегмента данного удаленного адреса, применив к нему любую арифметическую операцию. То есть с помощью арифметического оператора мы не можем перейти с одного сегмента на другой.
Если вы будете увеличивать дальний адрес сверх максимального значения его адреса смещения вместо увеличения адреса сегмента, он будет повторять свой адрес смещения в циклическом порядке. Это также называется упаковкой, т. Е. Если смещение равно 0xffff
и мы добавляем 1, то оно равно 0x0000
, и аналогично, если мы уменьшаем 0x0000
на 1, тогда оно равно 0xffff
и помним, что в сегменте изменений нет. 1033 *
Теперь я собираюсь сравнить огромные и дальние указатели:
1.При увеличении или уменьшении дальнего указателя ТОЛЬКО смещение указателя фактически увеличивается или уменьшается, но в случае большого указателя значение как сегмента, так и значения смещения будет меняться.
Рассмотрим следующий пример, взятый из ЗДЕСЬ :
int main()
{
char far* f=(char far*)0x0000ffff;
printf("%Fp",f+0x1);
return 0;
}
тогда вывод:
0000:0000
Нет изменений в значении сегмента.
А в случае огромных указателей:
int main()
{
char huge* h=(char huge*)0x0000000f;
printf("%Fp",h+0x1);
return 0;
}
Вывод:
0001:0000
Это связано с тем, что операция приращения изменяет не только значение смещения, но и значение сегмента. Это означает, что сегмент не изменится в случае указателей far
, а в случае указателя huge
может перемещаться из одного сегмента в другой.
2. Когда реляционные операторы используются на дальних указателях, сравниваются только смещения. Другими словами, реляционные операторы будут работать только на дальних указателях, если значения сегментов сравниваемых указателей совпадают. И в случае огромного это не произойдет, фактически происходит сравнение абсолютных адресов. Давайте разберемся с помощью примера указателя far
:
int main()
{
char far * p=(char far*)0x12340001;
char far* p1=(char far*)0x12300041;
if(p==p1)
printf("same");
else
printf("different");
return 0;
}
Выход:
different
В huge
указатель:
int main()
{
char huge * p=(char huge*)0x12340001;
char huge* p1=(char huge*)0x12300041;
if(p==p1)
printf("same");
else
printf("different");
return 0;
}
Выход:
same
Объяснение: Как мы видим, абсолютный адрес для p
и p1
равен 12341
(1234*10+1
или 1230*10+41
), но они не считаются равными в 1-м случае, потому что в случае указателей far
сравниваются только смещения, т. е. он будет проверять 0001==0041
. Что неверно.
А в случае огромных указателей операция сравнения выполняется на равных абсолютных адресах.
Дальний указатель никогда не нормализуется, но указатель huge
нормализуется. Нормализованный указатель - это тот, который имеет максимально возможный адрес в сегменте, а это означает, что смещение никогда не превышает 15.
предположим, что если у нас есть 0x1234:1234
, то нормализованная форма будет 0x1357:0004
(абсолютный адрес 13574
).
Огромный указатель нормализуется только тогда, когда с ним выполняется некоторая арифметическая операция, и не нормализуется во время присваивания.
int main()
{
char huge* h=(char huge*)0x12341234;
char huge* h1=(char huge*)0x12341234;
printf("h=%Fp\nh1=%Fp",h,h1+0x1);
return 0;
}
Выход:
h=1234:1234
h1=1357:0005
Объяснение: huge
указатель не нормализуется в случае присваивания. Но если над ним будет выполнена арифметическая операция, он будет нормализован. Так, h
равно 1234:1234
и h1
равно 1357:0005
, что нормализуется.
4. Смещение огромного указателя меньше 16 из-за нормализации и не так в случае дальних указателей.
давайте возьмем пример, чтобы понять, что я хочу сказать:
int main()
{
char far* f=(char far*)0x0000000f;
printf("%Fp",f+0x1);
return 0;
}
Выход:
0000:0010
В случае huge
указатель:
int main()
{
char huge* h=(char huge*)0x0000000f;
printf("%Fp",h+0x1);
return 0;
}
Output:
0001:0000
Объяснение: при увеличении дальнего указателя на 1 это будет 0000:0010
. И при увеличении огромного указателя на 1 будет 0001:0000
, поскольку его смещение не может быть больше 15, другими словами, оно будет нормализовано.