假设我有以下数组:
int list[3]={2,8,9};
printf("%p,%p,%p",(void*)&list[0],(void*)&list[1],(void*)&list[2]);
在使用C语言时,&list[0]<&list[1]<&list[2]是否总是保证成立?
我曾经认为这是一个硬性规定,但现在有人问我关于字节序
的问题,所以我必须非常确定它是否正确。
让我开始怀疑的是堆栈可以向上或向下增长
的问题。我对此不是很确定,因此非常感谢您详细的回答。谢谢。
假设我有以下数组:
int list[3]={2,8,9};
printf("%p,%p,%p",(void*)&list[0],(void*)&list[1],(void*)&list[2]);
在使用C语言时,&list[0]<&list[1]<&list[2]是否总是保证成立?
我曾经认为这是一个硬性规定,但现在有人问我关于字节序
的问题,所以我必须非常确定它是否正确。
让我开始怀疑的是堆栈可以向上或向下增长
的问题。我对此不是很确定,因此非常感谢您详细的回答。谢谢。
&list[0]<&list[1]
和 &list[1]<&list[2]
是有保证的。当比较同一数组元素的指针时,具有更大下标的元素指针将被认为具有更大的值。这在 C99 6.5.8@5 中有明确规定:
但是,不能保证使用指向具有较大下标值的数组元素的指针比指向同一数组具有较低下标值的元素的指针更大
%p
的 printf 打印的值也遵循相同的顺序 - 这些值是实现定义的。根据C标准(“第6.2.5节类型”):
...数组类型描述了一组连续分配的非空对象...
数组将在“内存”中连续分配。
Eric和Interjay所说的是,当我最初编写这篇文章时没有考虑到的内容,所以谢谢Eric和Interjay。他们说的是这仅适用于虚拟内存地址。
您的计算机和操作系统很可能使用内存管理单元(MMU),该单元创建虚拟地址空间(您正在其中工作),并将其映射到物理内存中的块大小块(页面)中。
因此,Eric和Interjay所说的是,虽然虚拟地址将是连续的,但它们映射到的物理内存块可能位于不同的地址。
Virtual Physical
+----------+ +----------+
| | |
| VMA pg 1 |---------->| PMA 88 (VMA1)
| | |
+----------+ +----------+
| |\ ...
| VMA pg 2 | \ ...
| | \ ...
+----------+ \ ...
\ \ ... big gap in physical
\ \ ... memory
\ \ ...
\ \ ...
\ >--+----------+
\ |
\ | PMA 999 (VMA2)
\ |
>-+----------+
因此,对于小数组(小于页面大小),VMA和PMA地址可能都是相同的,尽管最有可能PMA!= VMA。对于大于页面大小的数组,尽管VMA看起来是连续的,但是PMA可能会散乱无序,如上图所示...
此外,我认为Interjay和Eric正在进一步说明任何C地址,虽然在C模型中是连续的,但可能出现在内存的任何位置。虽然这很不可能,因为大多数操作系统实现了某种分页以获得虚拟到物理映射,但技术上可能是这种情况...学会考虑这一点是好的,所以感谢你们 :)
&(list[n])
我认为标准上等同于list+n
。在 C 中的数组索引符号不过是将值添加到指针的简写方式。内存保留的方式确保了+
的可用性。 - wirrbel