(为什么)使用未初始化变量的未定义行为? [英] (Why) is using an uninitialized variable undefined behavior?

查看:132
本文介绍了(为什么)使用未初始化变量的未定义行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有:

unsigned int x;
x -= x;

很明显, x 应该在此表达式之后为零,但我所看到的所有地方都说,该代码的行为是不确定的,不仅仅是 x (直到减法之前)。

it's clear that x should be zero after this expression, but everywhere I look, they say the behavior of this code is undefined, not merely the value of x (until before the subtraction).

两个问题:


  • 此代码的行为是否确实未定义?

    (例如,代码是否在兼容的系统上崩溃[或更糟]?)

  • Is the behavior of this code indeed undefined?
    (E.g. Might the code crash [or worse] on a compliant system?)

如果是的话, 为什么 会明确表示<$>行为是不确定的,因为<$> c $ c> x 在这里应该为零吗?

If so, why does C say that the behavior is undefined, when it is perfectly clear that x should be zero here?

ie通过在此处未定义行为给出的优点是什么?

i.e. What is the advantage given by not defining the behavior here?

很明显,编译器可以简单地在内部使用被视为方便的任何垃圾值变量,它将按预期工作...该方法出了什么问题?

Clearly, the compiler could simply use whatever garbage value it deemed "handy" inside the variable, and it would work as intended... what's wrong with that approach?

推荐答案

是的,此行为是不确定的,但对于

Yes this behavior is undefined but for different reasons than most people are aware of.

首先,使用单位化的值本身并不是未定义的行为,但是值只是不确定的。如果该值恰好是该类型的陷阱表示,则访问该对象将是UB。无符号类型很少具有陷阱表示形式,因此从那方面来讲,您将相对安全。

First, using an unitialized value is by itself not undefined behavior, but the value is simply indeterminate. Accessing this then is UB if the value happens to be a trap representation for the type. Unsigned types rarely have trap representations, so you would be relatively safe on that side.

使行为未定义的原因是变量的附加属性,即它可以已经用 register 声明过,这是从不使用其地址的。之所以会特别考虑此类变量,是因为有些架构具有真正的CPU寄存器,这些寄存器具有某种未初始化状态且与类型域中的值不对应的额外状态。

What makes the behavior undefined is an additional property of your variable, namely that it "could have been declared with register" that is its address is never taken. Such variables are treated specially because there are architectures that have real CPU registers that have a sort of extra state that is "uninitialized" and that doesn't correspond to a value in the type domain.

编辑:该标准的相关短语为6.3.2.1p2:

The relevant phrase of the standard is 6.3.2.1p2:


左值表示一个自动存储持续时间的对象,它可能已经用寄存器存储类声明了
(从未将其地址取到
),并且该对象未初始化(未使用初始化器声明
)。尚未在使用
之前对其执行任何分配),则该行为是不确定的。

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.

以下代码在所有情况下都是合法的:

And to make it clearer, the following code is legal under all circumstances:

unsigned char a, b;
memcpy(&a, &b, 1);
a -= a;




  • 这里 a b 被采用,因此它们的值只是不确定的

  • 由于 unsigned char 从来没有陷阱表示
    的不确定值只是未指定,任何 unsigned char 的值都可能发生

  • 最后 a 必须保持值 0

    • Here the addresses of a and b are taken, so their value is just indeterminate.
    • Since unsigned char never has trap representations that indeterminate value is just unspecified, any value of unsigned char could happen.
    • At the end a must hold the value 0.
    • Edit2: a b 具有未指定的值:

      a and b have unspecified values:


      3.19.3 未指定的值

      在任何情况下本国际标准均不要求选择
      的值时相关类型的有效值

      3.19.3 unspecified value
      valid value of the relevant type where this International Standard imposes no requirements on which value is chosen in any instance

      这篇关于(为什么)使用未初始化变量的未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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