简体   繁体   English

C++中布尔值转换的变量定义

[英]Variable definition to boolean value conversion in C++

I discovered that the below code is valid in C++98 and above:我发现以下代码在 C++98 及更高版本中有效:

if (int x = 7) {              // int x; if (x = 7) makes sense
  std::cout << x << '\n';     // 7 is printed
}

Question: what are the rules that govern the conversion of a variable definition to a boolean expression?问题:控制变量定义到布尔表达式的转换的规则是什么?

If it was like the below, it would make sense b/c the if condition is an assignment expression that would evaluate to an integer:如果它像下面那样,那么 b/c if 条件是一个赋值表达式,它会计算为一个整数:

int x;
if (x = 7) {
  std::cout << x << '\n';
}

The result of an assignment expression is the assignment target, which in this case is x .赋值表达式的结果是赋值目标,在本例中为x Since bool(7) is true, the condition is true.由于bool(7)为真,条件为真。

A common use of this feature which is much more useful is like this:此功能的一个常见用法更有用,如下所示:

if (auto* x = get_some_pointer())
    // use x, which is known to be not null

Where the variable is declared has nothing to do with it.变量在哪里声明与它无关。 Following your example, this would do the same thing:按照你的例子,这会做同样的事情:

int x;
if (x = 7)
    // ...

The rules governing this piece of the grammar are in [stmt.pre]管理这部分语法的规则在[stmt.pre]

1 1

 condition:健康)状况:\n     expression表达\n     attribute-specifier-seq opt decl-specifier-seq declarator brace-or-equal-initializer属性说明符-seq opt decl-specifier-seq声明符大括号或等号初始化器

4 A condition that is not an expression is a declaration ([dcl.dcl]). 4不是表达式的条件是声明 ([dcl.dcl])。 The declarator shall not specify a function or an array.声明符不应指定函数或数组。 The decl-specifier-seq shall not define a class or enumeration. decl-specifier-seq 不应定义类或枚举。 If the auto type-specifier appears in the decl-specifier-seq, the type of the identifier being declared is deduced from the initializer as described in [dcl.spec.auto].如果 auto 类型说明符出现在 decl-specifier-seq 中,则声明的标识符的类型是从初始化程序中推导出来的,如 [dcl.spec.auto] 中所述。

6 The value of a condition that is an initialized declaration in a statement other than a switch statement is the value of the declared variable contextually converted to bool. 6在 switch 语句以外的语句中作为初始化声明的条件的值是根据上下文转换为 bool 的声明变量的值。 If that conversion is ill-formed, the program is ill-formed.如果该转换格式错误,则程序格式错误。 The value of a condition that is an initialized declaration in a switch statement is the value of the declared variable if it has integral or enumeration type, or of that variable implicitly converted to integral or enumeration type otherwise.在 switch 语句中作为初始化声明的条件的值是声明变量的值,如果它具有整数或枚举类型,或者该变量隐式转换为整数或枚举类型,否则。 The value of a condition that is an expression is the value of the expression, contextually converted to bool for statements other than switch;作为表达式的条件的值是表达式的值,对于 switch 以外的语句,上下文转换为 bool; if that conversion is ill-formed, the program is ill-formed.如果该转换格式错误,则程序格式错误。 The value of the condition will be referred to as simply “the condition” where the usage is unambiguous.条件的值将简单地称为“条件”,其中用法是明确的。

7 If a condition can be syntactically resolved as either an expression or the declaration of a block-scope name, it is interpreted as a declaration. 7如果条件可以在语法上解析为表达式或块范围名称的声明,则将其解释为声明。

8 In the decl-specifier-seq of a condition, each decl-specifier shall be either a type-specifier or constexpr . 8在条件的 decl-specifier-seq 中,每个 decl-specifier 要么是类型说明符,要么是constexpr

In the above text condition is the grammatical element that appears in the grammar productions of if (condition) , while (condition) and switch (condition) .上述文本中的condition是出现在if (condition) , while (condition)switch (condition)的语法产生式中的语法元素。 Most other mentions of condition in [stmt.stmt] deal with its value after conversion to a boolean or an integral value (in switches). [stmt.stmt] 中大多数其他提到的condition在转换为布尔值或整数值(在开关中)后处理其值。 And the behavior based on the value is what one would expect.而基于价值的行为正是人们所期望的。

The only other thing of note that is mentioned elsewhere, is the behavior of the declaration with regard to its declarative region.在别处提到的唯一另一件值得注意的事情是声明关于其声明区域的行为。 For instance, in an if statement例如,在 if 语句中

if(auto handle = getHandle())
  handle->foo();
else
  handle->bar();

The name is available in both branches.该名称在两个分支中均可用。 But that is mentioned at [basic.scope.block]但这在[basic.scope.block] 中提到

3 Names declared in the init-statement, the for-range-declaration, and in the condition of if, while, for, and switch statements are local to the if, while, for, or switch statement (including the controlled statement), and shall not be redeclared in a subsequent condition of that statement nor in the outermost block (or, for the if statement, any of the outermost blocks) of the controlled statement. 3在 init-statement、for-range-declaration 以及 if、while、for 和 switch 语句的条件中声明的名称是 if、while、for 或 switch 语句(包括受控语句)的局部名称,并且不应在该语句的后续条件中或在受控语句的最外层块(或对于 if 语句,任何最外层块)中重新声明。 [ Example: [ 例子:

 if (int x = f()) { int x; // error: redeclaration of x } else { int x; // error: redeclaration of x }

— end example ] — 结束示例 ]

Like C, C++ booleans are treated as integers with value 0 or 1. When converting from other values it will parse the boolean as false if the value is zero, every other number becomes true.与 C 一样,C++ 布尔值被视为值为 0 或 1 的整数。当从其他值转换时,如果值为 0,它会将布尔值解析为 false,如果值为零,则每隔一个数字变为 true。

This enables easy null checks for pointers (which can also be interpreted as numbers) where a pointer with a value of 0 is the null pointer.这可以轻松检查指针(也可以解释为数字),其中值为 0 的指针是空指针。

The result of any assignment statement is the value of the left operand after the assignment.任何赋值语句的结果都是赋值后左操作数的值。

The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false.零值(对于整数、浮点和无作用域枚举)以及空指针和指向成员的空指针值变为假。 All other values become true.所有其他值都变为真。

So here the int x has a value of 7 becomes true.所以这里 int x 的值为 7 变为真。

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

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