简体   繁体   English

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

[英]Does this self-assignment do something sensible?

I just found this line of code within a function, which puzzles me. 我刚刚在一个函数中找到了这行代码,这让我很困惑。 Can this make sense in any context or it is undefined behavior? 这在任何情况下都有意义,还是未定义的行为?

char * acFilename = acFilename;

EDIT: The compiler complains with Warning C4700, that I am using an uninitialized variable. 编辑:编译器抱怨警告C4700,我正在使用未初始化的变量。

At block scope, in C++, this is undefined behaviour, as the right-hand side reads the variable the variable before it has been initialized (C++14 [dcl.init]/12). 在块范围内,在C ++中,这是未定义的行为,因为右侧在变量初始化之前读取变量 (C ++ 14 [dcl.init] / 12)。

At block scope, in C11, this could either be undefined behaviour or behave as an uninitialized variable, depending on various details of the implementation and the rest of the function, see here for detailed analysis. 在块范围内,在C11中,这可能是未定义的行为或表现为未初始化的变量,具体取决于实现的各种细节和函数的其余部分, 请参见此处进行详细分析。

At namespace scope, in C++, it is OK well-defined and makes a null pointer. 在命名空间范围内,在C ++中, 可以 很好地定义并生成空指针。 This is because all static variables are zero-initialized before their initializers are considered. 这是因为在考虑初始化器之前,所有静态变量都是零初始化的。 (C++14 [basic.start.init]/2). (C ++ 14 [basic.start.init] / 2)。

At file scope in C, it is a constraint violation; 在C中的文件范围内,它是一个约束违规; static variables must have a constant expression as initializer, and the value of a variable cannot be a constant expression. 静态变量必须具有常量表达式作为初始化程序,并且变量的值不能是常量表达式。

No this code does not make any sense. 没有这个代码没有任何意义。 It's probably a typo, maybe somebody meant to use 这可能是一个错字,也许有人打算使用

char* acFilename = ::acFilename;

or 要么

char* acFilename = m_acFilename;

or something else. 或者是其他东西。

As it stands, it's confusing and unhelpful at best, probably a bug because somebody meant to use a different variable. 就目前而言,它充其量只是令人困惑和无益,可能是一个错误,因为有人想要使用不同的变量。

I've seen this before. 我以前见过这个。 Since gcc is quite trigger happy with its uninitialized variable warnings this is a trick to silence those warnings. 由于gcc对其未初始化的变量警告非常满意,因此这是使这些警告静音的技巧。 Not sure if it's intentional design choice by gcc or the compiler just being stupid, but I've seen people do this on purpose to make gcc shut up (and in the process break the warning that might be correct in the future). 不确定这是gcc的故意设计选择还是编译器只是愚蠢的,但我看到人们故意这样做以使gcc闭嘴(并且在此过程中打破了将来可能正确的警告)。

I would just replace it with an initialization to NULL. 我只需将其初始化为NULL替换它。 This is a bad habit, doesn't work on other compilers and a NULL can't be less correct than an indeterminate value and undefined behavior. 这是一个坏习惯,不适用于其他编译器,并且NULL不能比不确定的值和未定义的行为更正确。

Just to demonstrate how this works (and also because I wanted to know if newer gcc versions still do this): 只是为了演示这是如何工作的(也是因为我想知道更新的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)
$

At some locations within a program, it may be possible for a variable to be in either of the following conditions: 在程序中的某些位置,变量可能处于以下任一条件:

  1. Inputs that have been received have caused the variable to be written, and will also cause code to use its value in future. 已接收的输入已导致变量被写入,并且还将导致代码在将来使用其值。

  2. Inputs that have been received have caused the variable not to be written, but will also cause code not to make any use of its value. 已收到的输入导致变量不被写入,但也会导致代码不使用其值。

Some compilers will squawk if they see that there exist inputs which would cause a variable to not to get written, and there exist inputs which would cause the variable to be read. 如果某些编译器看到存在会导致变量无法写入的输入,并且存在会导致变量被读取的输入,则会发出尖叫声。 Even if the only input which would cause the variable to get read would also cause it to get written, the compilers may not realize that. 即使导致变量被读取的唯一输入也会导致它被写入,编译器可能也没有意识到这一点。 While it would be possible to silence the compiler's complaints by unconditionally initializing the variable, machine code which initializes the variable with a value which can never actually get used would serve no functional purpose. 虽然可以通过无条件地初始化变量来使编译器的抱怨变得沉默,但是使用永远不会被实际使用的值来初始化变量的机器代码将不起作用。 A source code construct which would silence the compiler's complaints but not result in the compiler generating useless machine code may thus be preferable to one which would need to generate useless machine code. 因此,源代码构造会使编译器的抱怨无效但不会导致编译器生成无用的机器代码,因此可能优于需要生成无用机器代码的源代码构造。 On some compilers, a self-initializing declaration may serve such a purpose. 在某些编译器中,自我初始化声明可能起到这样的作用。

If a type has trap representations, there may be no practical alternative to writing an initialization that a compiler will likely turn into useless machine code, but if a type doesn't have trap representations there is no particular reason why a quality compiler should force programmers to ask for useless code they don't want and don't need. 如果一个类型有陷阱表示,那么编写初始化可能没有实际的替代方法,编译器可能会变成无用的机器代码,但是如果一个类型没有陷阱表示,那么质量编译器应该强制程序员没有特别的理由要求他们不想要和不需要的无用代码。 Rather than try to have different rules for platforms where various types do and don't have trap representations, however, the authors of the Standard defer to implementers' judgments as to what sorts of behavior would be sensible on for a particular target platform and application field. 然而,标准的作者并没有试图为各种类型的做法和没有陷阱表示的平台设置不同的规则,而是推迟实施者对于特定目标平台和应用程序的哪种行为是明智的判断领域。

If on some platform a compiler couldn't allow programmers to omit initialization for variables which are copied but otherwise unused without having to generate likely-redundant initializations itself, it would make sense to require the programmer to include initializations in all situations that could actually occur. 如果在某些平台上,编译器不允许程序员忽略复制的初始化,而这些变量被复制但未使用而不必自己生成可能冗余的初始化,那么要求程序员在所有可能实际发生的情况下包含初始化是有意义的。 。 On another platform where copying a meaningless value would simply cause the destination to hold a meaningless value, however, it would generally make more sense to allow a programmer to omit initialization in cases where none of the copies would ever end up getting used for any real purpose. 在另一个平台上,复制无意义的值只会导致目标保持无意义的值,但是,在没有任何副本最终会被用于任何实际的情况下,允许程序员省略初始化通常会更有意义。目的。 The authors of the Standard make no effort to specify what would make sense in any particular case, because they expect that people writing implementations should be capable of exercising good judgment. 标准的作者没有努力指出在任何特定情况下有意义的东西,因为他们期望编写实现的人应该能够做出良好的判断。

The best approach for dealing with this situation would probably be to write a macro which accepts a variable, and whose expansion will initialize the variable to zero (for implementations whose authors judge that there is more value in allowing the compilers to jump the rails when an uninitialized variable is copied, even if none of the copies are really "used" for anything, than there would be in guaranteeing that the mere act of copying a variable will have no side-effects) or else do nothing (when using an implementation which will stay on the rails even without the useless initialization). 处理这种情况的最佳方法可能是编写一个接受变量的宏,并且其扩展会将变量初始化为零(对于其作者判断允许编译器跳转轨道的更多值的实现未初始化的变量被复制,即使没有任何副本真正“用于”任何东西,也不会保证复制变量的行为没有副作用)或者什么都不做(当使用实现时即使没有无用的初始化,它也会保持在轨道上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM