数组的元素是否保证从较低地址存储到较高地址?
假设我有以下数组:
int list[3]={2,8,9}; printf("%p,%p,%p",(void*)&list[0],(void*)&list[1],(void*)&list[2]);
是否始终保证&list [0] <&list [1] <&list [2] ?
我曾经认为使用C时它是一个严格而快速的规则,但现在必须非常肯定它作为一个OP只是在我回答关于endianness
问题时问我这个问题
小端或大端
让我第二个想法的是stacks can grow up or down
我不是很确定,所以你的严谨答案是值得赞赏的。谢谢。
是的,保证&list[0]<&list[1]
和&list[1]<&list[2]
。 当比较指向同一数组元素的指针时,指向具有较大下标的元素的指针将被视为具有更大的值。 这在C99 6.5.8@5中规定:
指向具有较大下标值的数组元素的指针比指向具有较低下标值的相同数组的元素的指针要大
但是,不能保证printf与%p
打印的值也遵循相同的顺序 - 这些值是实现定义的。
从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) \ | >-+----------+
因此,对于小型arrays(小于页面大小),对于VMA和PMA地址都可能是这样,尽管很可能是PMA!= VMA。 对于大于页面大小的数组,尽管VMA看起来是连续的,但PMA可能是不相交的并且不正常,如上图所示…
此外,我认为Interjay和Eric更进一步说,任何C地址虽然在C模型中是连续的,但可能在内存中的任何地方。 虽然这不太可能,因为大多数操作系统实现某种分页以获得虚拟到物理映射,但从技术上讲,我认为……这很好学习,所以感谢chaps 🙂
如果您询问内存如何出现在C模型中,那么数组在C代码中似乎是连续的,并且C表达式&list[0] < &list[1]
为真。
如果您询问实际内存如何出现在C实现中,则C标准不需要在内存中任何特定的数组排列。 大多数C实现使用连续的升序虚拟内存用于数组,但降序地址将是一个简单的变体。 并且,在物理内存级别,arrays通常不是连续的,因为从虚拟内存到物理内存的映射由操作系统基于其可用的任何内容来确定,甚至可能在执行过程期间发生变化。
此外,无法保证%p
打印的字符串是内存地址。