【问题标题】:How reading beyond end of buffer works in C?超出缓冲区末尾的读取如何在 C 中工作?
【发布时间】:2020-10-29 16:03:26
【问题描述】:

创建这个x.c 测试文件:

int main(void)
{
  char x[2] = {3};
  return x[2];
}

然后运行

gcc x.c; ./a.out; echo $?

结果是:64

为什么是64

顺便说一句,为什么我们使用

return x[1];

我们得到0?为什么{3} 也没有初始化x[1]

【问题讨论】:

  • 你撬开一个属于别人的、你无权使用的保险箱,发现了 64 美元。为什么是 64 美元?为什么不是空的?为什么不是 10 或 100 或 1000 或吉娃娃?可能是因为拥有保险箱的人可以随意存放他们喜欢的东西吗?
  • 关于数组的部分初始化,请看:stackoverflow.com/questions/15520880/…
  • @Lundin 为什么如果我们添加x[2] = 5; 返回值是5
  • 因为当您将 5 美元放入您一直闯入的保险箱时,警察没有抓住您。并且您很幸运,所有者没有出现更改内容。
  • @Lundin 在这种情况下不应该发生“分段错误”吗?

标签: arrays c initialization


【解决方案1】:

在 C 中如何读取超出缓冲区末尾的内容?为什么是 64?

它不起作用,它是undefined behaviour 的结果。 x[2] 处不存在数组元素。

我们得到0?为什么{3} 也没有初始化x[1]

也就是说,像这样的声明

 char x[2] = {3};

创建一个数组x,其中包含两个元素,分别由x[0]x[1] 访问,并将x[0] 初始化为3,将任何剩余元素初始化为0(根据初始化规则,其中有更少数组元素的初始值设定项的数量)。因此,{3} 不会将所有数组元素初始化为值 3,而是仅设置第一个元素的值。

引用C11,第 6.7.9/P21 章

如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小数组的字符串文字中的字符少于数组中的元素,聚合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同。

【讨论】:

  • 我能想到的唯一可能的原因是“因为你的完美答案,我现在没有机会获得任何声誉来制作另一个答案。”干杯。
  • @RubberBee 现在已经消失了,希望我的编辑没有让情况变得更糟。 :P
  • 不,现在更多。
  • 为什么如果我们添加x[2] = 5;返回值是5
猜你喜欢
  • 1970-01-01
  • 2020-01-26
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 2021-11-28
  • 2012-03-15
  • 1970-01-01
相关资源
最近更新 更多