这种自我指派是否做了明智的事情?

时间:2017-02-21 11:01:18

标签: c++ c

我刚刚在一个函数中找到了这行代码,这让我很困惑。这在任何情况下都有意义,还是未定义的行为?

char * acFilename = acFilename;

编辑:编译器抱怨警告C4700,我正在使用未初始化的变量。

4 个答案:

答案 0 :(得分:59)

在块范围内,在C ++中,这是未定义的行为,作为初始化之前的变量的右侧reads the variable(C ++ 14 [dcl.init] / 12)。

在块范围内,在C11中,这可能是未定义的行为,或者表现为未初始化的变量,具体取决于实现的各种细节以及函数的其余部分see here以进行详细分析。

在命名空间范围内,在C ++中, OK 定义良好并生成空指针。这是因为在考虑初始化器之前,所有静态变量都是零初始化的。 (C ++ 14 [basic.start.init] / 2)。

在C中的文件范围内,它是一个约束违规;静态变量必须具有常量表达式作为初始化程序,并且变量的值不能是常量表达式。

答案 1 :(得分:24)

这段代码没有任何意义。它可能是一个错字,也许有人打算使用

R=301

char* acFilename = ::acFilename;

或其他。

就目前而言,它充其量只是令人困惑和无益,可能是一个错误,因为有人想要使用不同的变量。

答案 2 :(得分:19)

我之前见过这个。由于gcc对其未初始化的变量警告非常满意,因此这是使这些警告静音的技巧。不确定这是gcc的故意设计选择还是编译器只是愚蠢的,但我看到人们故意这样做以使gcc闭嘴(并且在此过程中打破了将来可能正确的警告)。

我只需将其初始化为NULL替换它。这是一个坏习惯,不适用于其他编译器,并且NULL不能比不确定的值和未定义的行为更正确。

只是为了演示这是如何工作的(也是因为我想知道更新的gcc版本是否仍然这样做):

$ cat foo.c
int
foobar(void)
{
    int foo;
    return foo + foo;
}
$ cc -c -Wall -O2 foo.c
foo.c: In function ‘foobar’:
foo.c:6:13: warning: ‘foo’ is used uninitialized in this function [-Wuninitialized]
  return foo + foo;
         ~~~~^~~~~
$ ed foo.c
[...]
$ cc -c -Wall -O2 foo.c
$ cat foo.c
int
foobar(void)
{
    int foo = foo;
    return foo + foo;
}
$ cc -c -Wall -O2 foo.c
$ cc -v
[...]
gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12)
$

答案 3 :(得分:2)

在程序中的某些位置,变量可能处于以下任一条件:

  1. 已收到的输入导致写入变量,并且还会导致代码在将来使用其值。

  2. 收到的输入导致变量不被写入,但也会导致代码不使用其值。

  3. 如果某些编译器看到存在会导致变量无法写入的输入,并且存在会导致变量被读取的输入,则会发出尖叫声。即使导致变量被读取的唯一输入也会导致它被写入,编译器可能也没有意识到这一点。虽然可以通过无条件地初始化变量来使编译器的抱怨变得沉默,但是使用永远不会被实际使用的值来初始化变量的机器代码将不起作用。源代码构造可以使编译器的抱怨静音但不会导致编译器生成无用的机器代码,因此可能优于需要生成无用机器代码的源代码构造。在某些编译器中,自我初始化声明可能有此目的。

    如果某个类型有陷阱表示,那么编写初始化可能没有实际的替代方法,编译器可能会变成无用的机器代码,但如果某个类型没有陷阱表示,则没有特别的理由为什么高质量的编译器应该迫使程序员要求他们不想要和不需要的无用代码。然而,标准的作者不是试图对各种类型的平台和不具有陷阱表示的平台设置不同的规则,而是遵从实施者的要求。判断哪种行为对特定的目标平台和应用领域是明智的。

    如果在某个平台上,编译器不允许程序员省略对复制但未使用的变量的初始化,而不必自己生成可能冗余的初始化,那么要求程序员在所有初始化中包含初始化是有意义的。实际可能发生的情况。在另一个平台上,复制无意义的值只会导致目标保持无意义的值,但是,在没有任何副本最终会被用于任何实际的情况下,允许程序员省略初始化通常会更有意义。目的。标准的作者没有努力指出在任何特定情况下有意义的东西,因为他们期望编写实现的人应该能够做出良好的判断。

    处理这种情况的最佳方法可能是编写一个接受变量的宏,并且其扩展会将变量初始化为零(对于作者判断允许编译器跳过更多值的实现)当复制未初始化的变量时,即使没有任何副本真正被用于任何事物,也不会保证只复制变量的行为没有副作用什么都不做(当使用一个即使没有无用的初始化也会保持在轨道上的实现)。