c – 巨大指针中的规范化意味着什么

前端之家收集整理的这篇文章主要介绍了c – 巨大指针中的规范化意味着什么前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我对理解“远”指针和“巨大”指针之间的区别感到很困惑,在谷歌搜索它的所有解决方案,找不到一个.任何人都能解释我两者之间的区别.此外,与巨大指针相关的精确归一化概念是什么.

请不要给我以下或任何类似的答案:

“The only difference between a far pointer and a huge pointer is that a huge pointer is normalized by the compiler. A normalized pointer is one that has as much of the address as possible in the segment,meaning that the offset is never larger than 15. A huge pointer is normalized only when pointer arithmetic is performed on it. It is not normalized when an assignment is made. You can cause it to be normalized without changing the value by incrementing and then decrementing it. The offset must be less than 16 because the segment can represent any value greater than or equal to 16 (e.g. Absolute address 0x17 in a normalized form would be 0001:0001. While a far pointer could address the absolute address 0x17 with 0000:0017,this is not a valid huge (normalized) pointer because the offset is greater than 0000F.). Huge pointers can also be incremented and decremented using arithmetic operators,but since they are normalized they will not wrap like far pointers.”

这里的归一化概念没有得到很好的解释,或者我可能无法理解它.

任何人都可以从初学者的角度尝试解释这个概念.

谢谢,
Rahamath

解决方法

开始时8086是8位处理器8085的扩展.8085只能用16位地址总线寻址65536字节.当英特尔开发8086时,他们希望软件尽可能与旧的8位处理器兼容,因此他们引入了分段存储器寻址的概念.这允许运行8位软件以生活在更大的地址范围内而不会注意到. 8086具有20位地址总线,因此可以处理高达1 MB的内存(2 ^ 20).不幸的是,它不能直接解决这个内存,它必须使用段寄存器来做到这一点.通过将向左移位4的16位段值加到16位偏移量来计算实际地址.
Example:
Segment  0x1234   Offset 0x5678 will give the real address
   0x 1234
  +0x  5678
  ---------
  =0x 179B8

正如您将注意到的,此操作不是双射的,这意味着您可以使用其他段和偏移的组合生成实际地址.

0x 1264               0x 1111
  +0x  5378             +0x  68A8
  ---------             ---------     etc.
  =0x 179B8             =0x 179B8

实际上有4096种不同的组合,因为3个重叠的半字节(3 * 4 = 12位,2 ^ 12 = 4096).
归一化组合是4096个可能值中唯一一个将偏移的3个高半字节归零的组合.在我们的例子中,它将是:

0x 179B
  +0x  0008
  ---------
  =0x 179B8

far和big指针之间的差异不在规范化中,你可以有非规范化的巨大指针,它是绝对允许的.不同之处在于执行指针运算时生成代码.使用far指针向指针递增或添加值时,将不会有溢出处理,您将只能处理64K的内存.

char far *p = (char far *)0x1000FFFF;
p++;
printf("p=%p\n");

将打印1000:0000
对于巨大的指针,编译器将生成处理转移所需的代码.

char huge *p = (char huge *)0x1000FFFF;
p++;
printf("p=%p\n");

将打印2000:0000

这意味着在使用远或大指针时必须要小心,因为使用它们的算术成本是不同的.

人们也不应该忘记,大多数16位编译器都有没有正确处理这些情况的库,有时会提供有缺陷的软件.微软实模式编译器没有处理其所有字符串函数的巨大指针. Borland甚至更糟糕,即使mem函数(memcpy,memset等)也没有处理偏移溢出.这就是为什么使用带有这些库函数的规范化指针是个好主意的原因,偏移溢出的可能性随之降低.

猜你在找的C&C++相关文章