是unsigned char型A [4] [5];一个[1] [7];未定义行为? [英] Is unsigned char a[4][5]; a[1][7]; undefined behavior?

查看:257
本文介绍了是unsigned char型A [4] [5];一个[1] [7];未定义行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个从C标准未定义行为的例子中读取(J.2):

One of the examples of undefined behavior from the C standard reads (J.2):

- 一个数组下标超出范围,即使对象是与明显访问
  定标(如在左值前pression一个[1] [7]指定的声明INT
  一个[4] [5])(6.5.6)

— An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6)

如果该声明从改变int类型的[4] [5] unsigned char型A [4] [5] ,并访问 A [1] [7] 仍然导致未定义的行为?我的看法是,它没有,但我从其他人谁不同意听到的,我想看看其他一些想成为专家这样认为。

If the declaration is changed from int a[4][5] to unsigned char a[4][5], does accessing a[1][7] still result in undefined behavior? My opinion is that it does not, but I have heard from others who disagree, and I'd like to see what some other would-be experts on SO think.

我的理由是:


  • 通过6.2.6.1条第4款和6.5第7段,物体重返presentation平常间pretation A 的sizeof(unsigned char型[4] [5])* CHAR_BIT 位,可以
    作为类型的数组访问 unsigned char型[20] 重叠的对象。

  • By the usual interpretation of 6.2.6.1 paragraph 4, and 6.5 paragraph 7, the representation of the object a is sizeof (unsigned char [4][5])*CHAR_BIT bits and can be accessed as an array of type unsigned char [20] overlapped with the object.

A [1] 的类型 unsigned char型[5] 作为左值,但在使用一个前pression(作为一个操作数的 [] 运营商,或等价作为操作数的 + 运营商 *(A [1] +7)),它衰变为类型的指针无符号字符*

a[1] has type unsigned char [5] as an lvalue, but used in an expression (as an operand to the [] operator, or equivalently as an operand to the + operator in *(a[1]+7)), it decays to a pointer of type unsigned char *.

A [1] 也是一个指向的重presentation的一个字节的值的形式 unsigned char型[20] 。国米$ P $这样PTED,增加7 A [1] 是有效的。

The value of a[1] is also a pointer to a byte of the "representation" of a in the form unsigned char [20]. Interpreted in this way, adding 7 to a[1] is valid.

推荐答案

谁愿意写一个符合编译器势必什么标准不得不说,而不是你的推理编译器供应商。标准指出,数组下​​标越界是不确定的行为,无任何例外,所以编译器允许炸毁​​。

A compiler vendor who wants to write a conforming compiler is bound to what the Standard has to say, but not to your reasoning. The Standard says that an array subscript out of range is undefined behaviour, without any exception, so the compiler is allowed to blow up.

要引用我是上次的讨论(注释<一个href=\"http://stackoverflow.com/questions/2832970/does-c99-guarantee-that-arrays-are-contiguous\">http://stackoverflow.com/questions/2832970/does-c99-guarantee-that-arrays-are-contiguous)

To cite my comment from our last discussion (http://stackoverflow.com/questions/2832970/does-c99-guarantee-that-arrays-are-contiguous)

你原来的问题是 A [0] [6] ,与声明 char的一个​​[5] [5] 这是UB,不管什么是有效的使用的char * p =&安培; A [3] [4]; 和访问 p [0] p [5] 服用地址&安培; p [6] 仍然有效,但访问 p [6] 是对象,从而UB。访问 A [0] [6之外] 是对象外 A [0] ,其类型数组的char [5],结果的类型是无关紧要的,它你如何达到这一点很重要。

"Your original question was for a[0][6], with the declaration char a[5][5]. This is UB, no matter what. It is valid to use char *p = &a[3][4]; and access p[0] to p[5]. Taking the address &p[6] is still valid, but accessing p[6] is outside of the object, thus UB. Accessing a[0][6] is outside of the object a[0], which has type array[5] of chars. The type of the result is irrelevant, it is important how you reach it."

编辑:

有未定义行为不够的情况下,你必须在整个标准进行扫描,搜集事实,并结合他们最后得到的未定义行为的结论。这一个是的明确,你甚至引用从标准的句子在你的问题。它是明确的,留下了任何变通办法没有空间。

There are enough cases of undefined behaviour where you have to scan through the whole Standard, collect the facts and combine them to finally get to the conclusion of undefined behaviour. This one is explicit, and you even cite the sentence from the Standard in your question. It is explicit and leaves no space for any workarounds.

我只是想知道如何推理更加明晰,你从我们的期望变成确信这真的是UB?

I'm just wondering how much more explicitness in reasoning do you expect from us to become convinced that it really is UB?

编辑2:

通过标准的挖掘和收集信息后,这里是另一个相关文献:

After digging through the Standard and collecting information, here is another relevant citation:

6.3.2.1 - 3:除了当它是sizeof操作符或的操作数
  一元&安培;操作者,或者是一个字符串
  文字用于初始化数组,
  有型'的阵列的前pression
  类型''转换为一个前pression
  类型'指向类型''那
  指向的初始元素
  数组对象和是不是左值。如果
  数组对象具有寄存器存储
  类,行为是不确定的。

6.3.2.1 - 3: Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

所以我觉得这是有效的:

So I think this is valid:

unsigned char *p = a[1]; 
unsigned char c = p[7]; // Strict aliasing not applied for char types

这是UB:

unsigned char c = a[1][7];

由于 A [1] 是不是在这一点上左值,但进一步的评估,违反J.2一个数组下标越界。到底发生了什么应该依赖于编译器实际上是如何实现在多维数组的数组索引。所以,你可能是正确的,它不会使有关任何已知实施任何区别。但是,这是一个有效的未定义的行为,太。 ;)

Because a[1] is not an lvalue at this point, but evaluated further, violating J.2 with an array subscript out of range. What really happens should depend on how the compiler actually implements the array indexing in multidimensional arrays. So you may be right that it doesn't make any difference on every known implementation. But that's a valid undefined behaviour, too. ;)

这篇关于是unsigned char型A [4] [5];一个[1] [7];未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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