当两个指针都指向同一个数组的元素时,C 标准保证了指针比较的有效性,但是在系统中通常如何确保这一点?
编译器可能会让您在有符号和无符号指针之间进行选择。编译器将生成进行比较的程序集。但是编译器不分配内存。例如,如果您使用有符号指针进行编译,编译器如何知道运行时不会为跨越有符号溢出中断的数组分配块?
当两个指针都指向同一个数组的元素时,C 标准保证了指针比较的有效性,但是在系统中通常如何确保这一点?
编译器可能会让您在有符号和无符号指针之间进行选择。编译器将生成进行比较的程序集。但是编译器不分配内存。例如,如果您使用有符号指针进行编译,编译器如何知道运行时不会为跨越有符号溢出中断的数组分配块?
编译器可能会让您在有符号和无符号指针之间进行选择。编译器将生成进行比较的程序集。但是编译器不分配内存。例如,如果您使用有符号指针进行编译,编译器如何知道运行时不会为跨越有符号溢出中断的数组分配块?
换句话说,一个典型的实现如何确保没有用户数据跨越地址0x80000000
或0x00000000
. 好吧,在流行的桌面操作系统上,您可以免费获得此保证,因为0x00000000
它位于内核空间(您的用户空间程序无法访问)并且0x80000000
......好吧,我实际上不再了解 32 位机器了。但是在 64 位机器上,0x8000000000000000
它实际上是在茫茫人海中——典型的 64 位操作系统根本不会在和(source)之间的巨大范围内映射任何东西。如果您有大量资源,那么留下数十亿字节未使用完全没有问题。(大量轻描淡写的警告!)0x0000FFFFFFFFFFFF
0xFFFF000000000000
现在,如果您在裸机上编程,那么您可能无法保证&a[7] < &a[8]
. 如果您在诸如 PowerPC 或 V800 之类的 RISC 目标上编程并利用位于地址周围的“小数据区” 0x0000
(访问速度很快,因为从这些地址加载不需要间接访问,则这种情况尤其可能发生)通过寄存器)。在这种情况下,您基本上是在鼓励编译器跨0x0000
边界拆分变量(更糟糕的是,允许&v == NULL
为真),以换取有价值的优化。
AFAIK,内存地址总是使用无符号的。如果您的代码以其他方式使用它们,则它不会很好地工作(除非您真的知道自己在做什么)。
在 C中没有强制执行这种正确性的机制。编写正确的代码取决于您。C 不是一种安全的语言。可以编写语法正确的代码,但不能构成有效的程序。