为什么零长度VLA UB? [英] Why Are Zero Length VLAs UB?

查看:108
本文介绍了为什么零长度VLA UB?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

2011年标准明确规定...

The 2011 standard explicitly states...

6.7.6.2数组声明符

6.7.6.2 Array declarators

  1. 如果size是一个不是整数常量表达式的表达式:如果它出现在一个整数中 函数原型作用域中的声明,将其视为已被替换 *;否则, 每次评估时,其值都应大于零.每个实例的大小 长度可变的数组类型在其生命周期内不会发生变化.如果大小表达式是sizeof运算符的操作数的一部分,并且更改大小表达式的值不会影响该运算符的结果,则不确定是否 大小表达式被求值.
  1. If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero. The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated.

它是人为设计的,但是以下代码似乎是合理的.

It's contrived, but the following code seems reasonable.

size_t vla(const size_t x) {

  size_t a[x];
  size_t y = 0;

  for (size_t i = 0; i < x; i++)
    a[x] = i;

  for (size_t i = 0; i < x; i++)
    y += a[i % 2];

  return y;
}

Clang似乎为其生成了合理的x64汇编(没有优化).显然,索引零长度的VLA没有任何意义,但超出范围访问会导致未定义的行为.

Clang seems to generate reasonable x64 assembly for it (without optimizations). Obviously indexing a zero length VLA doesn't make sense, but accessing beyond bounds invokes undefined behavior.

为什么零长度数组未定义?

Why are zero length arrays undefined?

推荐答案

int i = 0;
int a[i], b[i];

a == b吗?不应该-它们是不同的对象-但是避免它是有问题的.如果您无条件在ab之间留出空隙,则是在i > 0情况下浪费了空间.如果您检查是否i == 0并且仅留一个空白,那么您在i > 0情况下就是在浪费时间.

Is a == b? It shouldn't be - they're different objects - but avoiding it is problematic. If you leave a gap between a and b unconditionally, you're wasting space in the i > 0 case. If you check whether i == 0 and only leave a gap then, you're wasting time in the i > 0 case.

多维数组会变得更糟:

int i = 0;
int a[2][i];

您可以在两个变量之间填充,但在哪里可以填充?没有打破sizeof (int[2][i]) == 2 * i * sizeof (int)不变性的方法,这是不可能的.如果不填充,则a[0]a[1]具有相同的地址,并且您正在破坏另一个重要的不变式.

You can pad between two variables, but where could you pad here? There's no way to do it without breaking the invariant that sizeof (int[2][i]) == 2 * i * sizeof (int). If you don't pad, then a[0] and a[1] have the same address, and you're breaking a different important invariant.

这是一个不值得定义的头痛.

It's a headache that isn't worth defining.

这篇关于为什么零长度VLA UB?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆