正在使用未初始化的变量未定义行为

正在使用未初始化的变量未定义行为

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

问题描述

如果我有:

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 说 行为 是未定义的,而 x 此处应该为零?

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

即不在这里定义行为有什么优势?

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:

如果左值指定了一个自动存储持续时间的对象可以用寄存器存储类声明(从来没有取其地址),并且该对象未初始化(未声明)带有初始值设定项并且之前没有对其进行赋值使用),行为未定义.

为了更清楚,以下代码在任何情况下都是合法的:

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

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

  • 这里取的是ab的地址,所以它们的值就是不确定.
  • 因为 unsigned char 从来没有陷阱表示那个不确定的值只是未指定,unsigned char 的任何值都可以发生.
  • 最后a 必须保存值0.
    • Here the addresses of a and b are taken, so their value is justindeterminate.
    • Since unsigned char never has trap representationsthat indeterminate value is just unspecified, any value of unsigned char couldhappen.
    • At the end a must hold the value 0.
    • Edit2: ab 有未指定的值:

      a and b have unspecified values:

      3.19.3 未指定值
      相关类型的有效值,当本国际标准对哪个值没有要求时在任何情况下都被选中

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

08-21 13:32