【问题标题】:How does C guarantee that the memory address equaling the array value will be available? [closed]C如何保证等于数组值的内存地址可用? [关闭]
【发布时间】:2017-10-10 21:56:10
【问题描述】:
char str[] = 'hello';
printf("%x, %x", str, &str)

在C语言中,数组的值和数组的内存地址是一样的。

C 如何保证地址可用? 如果被拿走会怎样? 如果有两个具有相同值的数组怎么办?

【问题讨论】:

  • C 确实给你这个保证的假设来自哪里?
  • 我投票结束这个问题作为题外话,因为你的前提不正确,你的问题是基于一个巨大的误解。试图填补你的知识空白可能会导致长时间的开放式讨论。请参阅C FAQ 中的Arrays and Pointers。
  • 您误解了“数组的值”这个术语。
  • "在 C 中,数组的值和数组的内存地址是相同的。"是假的。因此,一旦您重新检查该信息,您的问题就会改变。
  • 顺便说一句:你想要char str[] = "hello"; " 而不是'?

标签: c arrays memory


【解决方案1】:

你似乎有一个根本性的误解,表达在这个不正确的评论中:

在C语言中,数组的值和数组的内存地址是一样的。

数组的值是其元素类型的对象序列。这与它的地址完全不同。

这种值在内存中的表示是元素类型对象的连续表示序列。这样的表示有一个地址。从该表示形式可以看出,它的地址与第一个数组元素的地址相同(在索引 0 处)。

您的困惑可能源于这样一个事实,即在几乎所有可能出现数组值或指定数组的左值的上下文中,在评估时它会被替换(有些人说“衰减到”)指向数组第一个元素的指针。这并不意味着数组值和指针是一回事。此外,在类型方面,替换不是数组的地址,而是元素的地址。这是一个微妙但重要的区别。

这几乎就是所有语言所要说的。提供符合行为的实现取决于实现,他们可以按照他们认为合适的方式进行操作。在实践中,实现为数组保留空间作为编译和链接过程的一部分(可能包括动态链接)或作为函数的机器代码的一部分,并且确定地址是什么。在某些情况下,地址将被插入到二进制文件中的一个或多个适当位置(这是链接的一个关键方面)。在其他情况下,地址将存储在内存中,并在必要时读取。或者在某些情况下,该地址可能仅在阵列的整个生命周期内保存在 CPU 寄存器中。你不需要关心。

【讨论】:

    【解决方案2】:

    您的理解或数组不完整。数组的地址是它的基本属性之一,没有它就无法定义数组。当您在没有[] 的情况下引用 C 中的数组时,您只需告诉编译器您指的是数组的基地址 - 这是存储第一个元素(索引 0)的内存地址。所有其他数组元素都在连续内存块中的第一个元素之后。

    当您访问一个数组槽时,您只需告诉编译器生成从内存地址相对于数组的基地址读取这么多字节(取决于数组的类型)的代码。您指定的插槽用于计算相对于基地址的偏移量。

    数组的定义(用最简单的术语来说)只是一组从特定内存地址开始的字节。数组的类型只是提示编译器在您从数组槽中检索值时应该生成的类型验证。语言本身可能会对数组施加更多抽象规则,但大多数(不是全部)具有数组的类 C 语言以相同的方式分配数组。

    当您(静态地)声明一个数组时,编译器会在一个可用位置为其分配空间 - 不可能(没有编译器错误或程序员错误)在同一个位置“放置两个数组”。如果您有两个分配在同一地址的数组变量,那么您将通过两个数组访问同一组底层字节。 (如果两个数组的类型不同,你可能通过两个数组看不到相同的值,但底层字节仍然相同)。

    当你动态分配一个数组时(例如,使用malloc(),内存分配器会寻找一个合适的空内存块来放置你的数组,并返回它选择的内存地址。如果一个合适的找不到内存块(例如,你的数组太大),你会得到某种形式的错误。

    【讨论】:

    • Hmmm " 一个数组和它的地址不是两个独立的、可区分的东西——它们是同一个。我会说他们不同char a[42]; sizeof(a) != sizeof(&a)
    • 说得很好,但我对“一个数组及其地址是 [...] 一个且相同的”有异议。他们绝对不一样。也许你的意思是说数组的地址是它的特征属性之一,或者类似的东西。
    • @JohnBollinger 现在好点了吗?
    • 不同意In C, there are no objects。 C 指定“对象”“执行环境中的数据存储区域,其内容可以表示值”。 C11 3.15 也许你正在考虑由其他语言定义的object。
    • "当你引用一个没有索引器的数组时,你把它用作指针" 反例:试试char a[42]; printf("%u\n", (unsigned) sizeof a); 你得到的是 42 还是像 4 或 8 这样的指针大小?跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 2019-04-07
    相关资源
    最近更新 更多