大指针中的规范化是什么意思

我对理解“远”指针和“巨大”指针之间的区别有很多困惑,在谷歌搜索它的所有解决方案,找不到。 任何人都能解释我两者之间的区别。 此外,与巨大指针相关的精确归一化概念是什么。

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

“far指针和一个巨大的指针之间的唯一区别在于,一个巨大的指针由编译器规范化。规范化指针是一个在段中具有尽可能多的地址的指针,意味着偏移量永远不会大于15只有在对它进行指针运算时,才会对一个巨大的指针进行归一化。当进行赋值时,它不会被归一化。你可以使它被归一化,而不是通过递增然后递减它来改变它。偏移量必须小于16。因为该段可以表示任何大于或等于16的值(例如,标准化forms的绝对地址0x17将是0001:0001 。虽然远指针可以用0000:0017寻址绝对地址0x17 ,但这不是有效的(标准化)指针,因为偏移量大于0000F 。)。巨大的指针也可以使用算术运算符递增和递减,但由于它们被标准化,因此它们不会像远指针那样换行。

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

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

谢谢,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 

farhuge指针之间的区别不在标准化中,你可以有非标准化的huge指针,它是绝对允许的。 不同之处在于执行指针运算时生成的代码。 使用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函数( memcpymemset等)也没有处理偏移溢出。 这就是为什么使用带有这些库函数的规范化指针是个好主意的原因,偏移溢出的可能性随之降低。

首先要理解的是分段指针如何转换为线性地址。 对于您的示例,转换是:

 linear = segment * 16 + offset; 

因此,在那里可以使用不同的段/偏移组合来表示相同的线性地址。 例如,以下段/偏移量组合都指向相同的线性地址:

 0004:0000 0003:0010 0002:0020 0001:0030 0000:0040 

这样做的问题是,如果ptr1的分段地址为0100:0000 ,ptr2的分段地址为0010:0020 ,则简单比较将确定ptr1 != ptr2即使它们实际指向同一地址。

规范化是将地址转换为表单的过程,这样如果两个非规范化指针引用相同的线性地址,它们都将转换为相同的规范化forms。

我记得,它是这样的:

  • 近指针指向同一段(作为指针)的内存。
  • 远指针指向另一个段中的内存。
  • 巨大的指针让你指向比段大的内存(所以你可以有一个块> 64k并对你的指针做算术,以及塞缪尔所说的)。

如果你是初学者,最好忘记你听说过Near / Far / Huge。 它们只适用于早期Intel 80×86上常见的旧16位分段存储器模型。 在32位和64位的范围内(即自1994年以来的所有内容),内存只是一个大的连续块,因此指针只是一个指针(就单个应用程序而言)。