如果 a 未初始化,a^a 或 a-a 是未定义的行为吗? [英] Is a^a or a-a undefined behaviour if a is not initialized?

查看:41
本文介绍了如果 a 未初始化,a^a 或 a-a 是未定义的行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个程序:

#include int main(void){无符号整数 a;printf("%u %u
", a^a, a-a);返回0;}

这是未定义的行为吗?

从表面上看,a 是一个未初始化的变量.所以这指向未定义的行为.但是对于 a 的所有值,a^aaa 都等于 0,至少我认为是案子.是否有可能以某种方式证明该行为是明确定义的?

解决方案

在 C11 中:

  • 根据 6.3.2.1/2,如果 a 从未获取其地址,则它是明确未定义的(引用如下)
  • 它可能是一个陷阱表示(访问时会导致 UB).6.2.6.1/5:
<块引用>

某些对象表示不需要表示对象类型的值.

无符号整数可以有陷阱表示(例如,如果它有 15 个精度位和 1 个奇偶校验位,访问 a 可能会导致奇偶校验错误).

6.2.4/6 表示初始值是不确定,而 3.19.2 下的定义是未指定值或陷阱表示.>

进一步:在 C11 6.3.2.1/2 中,Pascal Cuoq 指出:

<块引用>

如果左值指定了一个可以自动存储持续时间的对象使用 register 存储类声明(从未获取其地址),并且该对象未初始化(未使用初始化程序声明且未对其进行赋值)在使用之前执行),行为未定义.

这对字符类型没有例外,所以这个条款似乎取代了前面的讨论;即使不存在陷阱表示,访问 x 也立即未定义.此条款已添加到 C11 以支持 Itanium CPU实际上有一个寄存器的陷阱状态.

<小时>

没有陷阱表示的系统:但是如果我们加入 &x; 以便 6.3.2.1/2 的反对不再适用,我们会已知没有陷阱表示的系统?那么该值是一个未指定的值.3.19.3中unspecified value的定义有点模糊,不过DR 451,总结如下:

  • 在描述的条件下未初始化的值可能会改变其值.
  • 对不确定值执行的任何操作都会产生不确定值.
  • 库函数在用于不确定值时将表现出未定义的行为.
  • 这些答案适用于所有没有陷阱表示的类型.

在这个分辨率下,int a;&a;int b = a - a; 导致 b 仍然具有不确定的值.

请注意,如果不确定值未传递给库函数,我们仍处于未指定行为(而非未定义行为)的领域.结果可能很奇怪,例如if ( j != j ) foo(); 可以调用 foo,但恶魔必须留在鼻腔中.

Consider this program:

#include <stdio.h>

int main(void)
{
    unsigned int a;
    printf("%u %u
", a^a, a-a);
    return 0;
}

Is it undefined behaviour?

On the face of it, a is an uninitialized variable. So that points to undefined behaviour. But a^a and a-a are equal to 0 for all values of a, at least I think that is the case. Is it possible that there is some way to argue that the behaviour is well defined?

解决方案

In C11:

  • It's explicitly undefined according to 6.3.2.1/2 if a never has its address taken (quoted below)
  • It could be a trap representation (which causes UB when accessed). 6.2.6.1/5:

Certain object representations need not represent a value of the object type.

Unsigned ints can have trap representations (e.g. if it has 15 precision bits and 1 parity bit, accessing a could cause a parity fault).

6.2.4/6 says that the initial value is indeterminate and the definition of that under 3.19.2 is either an unspecified value or a trap representation.

Further: in C11 6.3.2.1/2, as pointed out by Pascal Cuoq:

If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

This doesn't have the exception for character types, so this clause appears to supersede the preceding discussion; accessing x is immediately undefined even if no trap representations exist. This clause was added to C11 to support Itanium CPUs which do actually have a trap state for registers.


Systems without trap representations: But what if we throw in &x; so that that 6.3.2.1/2's objection no longer applies, and we are on a system that is known to have no trap representations? Then the value is an unspecified value. The definition of unspecified value in 3.19.3 is a bit vague, however it is clarified by DR 451, which concludes:

  • An uninitialized value under the conditions described can appear to change its value.
  • Any operation performed on indeterminate values will have an indeterminate value as a result.
  • Library functions will exhibit undefined behavior when used on indeterminate values.
  • These answers are appropriate for all types that do not have trap representations.

Under this resolution, int a; &a; int b = a - a; results in b having indeterminate value still.

Note that if the indeterminate value is not passed to a library function, we are still in the realm of unspecified behaviour (not undefined behaviour). The results may be weird, e.g. if ( j != j ) foo(); could call foo, but the demons must remain ensconced in the nasal cavity.

这篇关于如果 a 未初始化,a^a 或 a-a 是未定义的行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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