C 数组的元素是否保证从较低的地址存储到较高的地址?

C 数组的元素是否保证从较低的地址存储到较高的地址?,c,arrays,stack,memory-address,C,Arrays,Stack,Memory Address,假设我有以下数组: int list[3]={2,8,9}; printf("%p,%p,%p",(void*)&list[0],(void*)&list[1],(void*)&list[2]); 如果您询问C模型中的内存是如何显示的,那么数组在C代码中显示为连续的,并且C表达式&list[0]

假设我有以下数组:

int list[3]={2,8,9};
printf("%p,%p,%p",(void*)&list[0],(void*)&list[1],(void*)&list[2]);

如果您询问C模型中的内存是如何显示的,那么数组在C代码中显示为连续的,并且C表达式
&list[0]<&list[1]
为真,是否总是保证&list[0]


如果您询问实际内存在C实现中是如何出现的,C标准不要求内存中有任何特定的数组排列。大多数C实现对数组使用连续递增的虚拟内存,但递减地址将是一个简单的变体。而且,在物理内存级别上,阵列通常不是连续的,因为从虚拟内存到物理内存的映射是由操作系统根据其可用的内容确定的,甚至可能在进程执行期间发生变化


此外,不能保证由
%p
打印的字符串是内存地址。

是的,可以保证C标准中的
&list[0](“第6.2.5节类型”):

 Virtual               Physical
+----------+           +----------+
|          |           |
| VMA pg 1 |---------->| PMA 88 (VMA1)
|          |           |
+----------+           +----------+
|          |\           ...
| VMA pg 2 | \          ...
|          |  \         ...
+----------+   \        ...
             \  \       ...  big gap in physical
              \  \      ...  memory
               \  \     ...
                \  \    ...
                 \  >--+----------+
                  \    |
                   \   | PMA 999 (VMA2)
                    \  |
                     >-+----------+
…数组类型描述连续分配的非空对象集

阵列将在“内存”中连续分配

埃里克和Injayy所说的,这是我最初编写的,所以谢谢埃里克和Injayi时,我没有考虑到的,这只适用于<强>虚拟<强>内存地址。

 Virtual               Physical
+----------+           +----------+
|          |           |
| VMA pg 1 |---------->| PMA 88 (VMA1)
|          |           |
+----------+           +----------+
|          |\           ...
| VMA pg 2 | \          ...
|          |  \         ...
+----------+   \        ...
             \  \       ...  big gap in physical
              \  \      ...  memory
               \  \     ...
                \  \    ...
                 \  >--+----------+
                  \    |
                   \   | PMA 999 (VMA2)
                    \  |
                     >-+----------+
您的机器和操作系统很可能使用内存管理单元(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模型中是连续的,但可能在内存中的任何地方。虽然这不太可能,因为大多数操作系统都实现了某种分页来获得虚拟到物理的映射,但从技术上讲,我认为可能是这样的。。。这是很好的学会考虑,所以感谢查普斯:

只有元素被存储在连续的位置EH中,如果高到低还是低到更高的地址并不重要吗?@ R u Pppel's秃秃:不,C标准不能保证数组元素被连续存储。它只要求C模型中的指针增量引用连续的数组元素。从C指针到机器地址的映射取决于C实现。@Jimbo你能在一个单独的答案中发表你对Eric答案的反驳吗?@Jimbo:所有C行为都是用抽象机器来描述的。该机器可以以C实现所需的任何方式实现。在C模型中,阵列地址必须看起来是连续的,但C标准没有对物理存储提出要求。事实上,大多数实现都使用连续的虚拟存储,但底层物理内存是由操作系统分配的,并且不是完全连续的。您的答案与Eric Postdischil的答案相矛盾吗?请两位提供更多细节。
&(list[n])
我认为每个标准等同于
list+n
。C中的数组索引表示法只不过是向指针添加值的缩写。内存的保留方式确保了
+
的有效性。您是在询问C中的事物是如何出现的还是它们在内存中的实际情况?@EricPostischil通过一条注释简单地告诉我您对这两方面的看法。尽管我对实际内存更感兴趣。数组在C模型中是连续的和升序的。该标准对物理实现没有任何要求。您应该指定其中一个,以便答案与问题相符。如果你想了解这两个问题,可以问两个问题。