【问题标题】:What is the problem of the following code in cc中以下代码的问题是什么
【发布时间】:2020-01-12 20:40:39
【问题描述】:
#include <stdio.h>

int main(){
    int a[1] = {1};
    int b = 6;
    printf("%d\n", a[-1]);
    printf("%d\n", b);
    //printf("%d\n", (a-1 == &b));
    return 0;
}

我写了上面的代码,发现在使用gcc或mingw编译时它不能正常工作,但是当我取消第8行的注释时,一切都很好。谁能帮我解释一下代码?

【问题讨论】:

标签: c memory


【解决方案1】:

a[-1] 是未定义的内存空间。

【讨论】:

  • 在我看来,堆栈增长到低地址,我在 a 之后声明 b,所以 b 假设在内存中的 a 下面,所以我可以使用 a[-1] 访问 b,如果我取消注释行8、一切都如我所料
  • @SolskGaer — 不保证变量的布局。一个编译器可能会像你期望的那样做;其他人可以做不同的事情。您试图利用未定义的行为;任何结果都是有效的。
  • @SolskGaer 如果没有考虑到某个系统,您将无法推理堆栈框架布局。此外,如果你的代码做了超出 C 标准范围的有问题的事情,编译器可能会生成错误的代码,而不管内存布局如何。
【解决方案2】:

数组的索引无效,我认为您的意思是 print a[1] printf("%d\n", a[-1])

【讨论】:

  • 感谢您的回复,我想使用a[-1]访问b
  • @SolskGaer ba 在内存中可能不是邻居,因此访问 b 是错误的。
  • #include &lt;stdio.h&gt; int main(){ int a[1] = {1}; int *b; b = a-1; printf("Adress of a, aka a[0]: %d\n", a); printf("Address of a-1: %d\n", a-1); printf("Address of b: %d\n",b); printf("Value b is pointing to: %d\n", *b); printf("Does the address of a== adress of b? %d\n", (a-1 == b)); return 0; }
  • @AgrudgeAmicus 当我取消注释第 8 行时,代码按预期工作,你能为我解释一下吗?谢谢
  • 你在期待什么
【解决方案3】:

a[-1]a-1 导致未定义的行为。首先,让我们从 C11 标准部分 6.5.2.1p2 中获取数组下标的定义:

后缀表达式后跟方括号中的表达式 [] 是一个下标 指定数组对象的元素。下标运算符的定义 [] 就是它 E1[E2] 等同于 (*((E1)+(E2))) .

所以数组下标在给指针加整数时遵循指针算术规则。

在 6.5.6p8 节定义指针算法时,它设置了一些规则和行为(强调我的)

如果两个指针 操作数和结果指向同一数组对象的元素,或最后一个元素 数组对象的元素,评估不应产生溢出; 否则, 行为未定义。 如果结果指向数组对象的最后一个元素,则它 不得用作一元的操作数 * 被评估的运算符。

您的问题中数组下标涉及的指针运算的结果在数组对象之外,因此会导致未定义的行为。

【讨论】:

    猜你喜欢
    • 2011-10-10
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多