简体   繁体   中英

C++ and left/right shift operators on a boolean

Consider the following program that tests the result of shift operators on boolean converted back to a boolean:

#include <iostream>
int main()
{
    std::cout<<"right shift: bool/bool"<<std::endl;
    std::cout<<"false << false = "<<bool(false << false)<<std::endl;
    std::cout<<"false << true = "<<bool(false << true)<<std::endl;
    std::cout<<"true << false = "<<bool(true << false)<<std::endl;
    std::cout<<"true << true = "<<bool(true << true)<<std::endl;
    std::cout<<std::endl;
    std::cout<<"right shift: bool/unsigned int"<<std::endl;
    std::cout<<"false << 0U = "<<bool(false << 0U)<<std::endl;
    std::cout<<"false << 1U = "<<bool(false << 1U)<<std::endl;
    std::cout<<"false << 2U = "<<bool(false << 2U)<<std::endl;
    std::cout<<"false << 100U = "<<bool(false << 100U)<<std::endl;
    std::cout<<"true << 0U = "<<bool(true << 0U)<<std::endl;
    std::cout<<"true << 1U = "<<bool(true << 1U)<<std::endl;
    std::cout<<"true << 2U = "<<bool(true << 2U)<<std::endl;
    std::cout<<"true << 100U = "<<bool(true << 100U)<<std::endl;
    std::cout<<std::endl;
    std::cout<<"right shift: bool/int"<<std::endl;
    std::cout<<"false << -100 = "<<bool(false << -100)<<std::endl;
    std::cout<<"false << -2 = "<<bool(false << -2)<<std::endl;
    std::cout<<"false << -1 = "<<bool(false << -1)<<std::endl;
    std::cout<<"false << 0 = "<<bool(false << 0)<<std::endl;
    std::cout<<"false << 1 = "<<bool(false << 1)<<std::endl;
    std::cout<<"false << 2 = "<<bool(false << 2)<<std::endl;
    std::cout<<"false << 100 = "<<bool(false << 100)<<std::endl;
    std::cout<<"true << -100 = "<<bool(true << -100)<<std::endl;
    std::cout<<"true << -2 = "<<bool(true << -2)<<std::endl;
    std::cout<<"true << -1 = "<<bool(true << -1)<<std::endl;
    std::cout<<"true << 0 = "<<bool(true << 0)<<std::endl;
    std::cout<<"true << 1 = "<<bool(true << 1)<<std::endl;
    std::cout<<"true << 2 = "<<bool(true << 2)<<std::endl;
    std::cout<<"true << 100 = "<<bool(true << 100)<<std::endl;
    std::cout<<std::endl;
    std::cout<<"left shift: bool/bool"<<std::endl;
    std::cout<<"false >> false = "<<bool(false >> false)<<std::endl;
    std::cout<<"false >> true = "<<bool(false >> true)<<std::endl;
    std::cout<<"true >> false = "<<bool(true >> false)<<std::endl;
    std::cout<<"true >> true = "<<bool(true >> true)<<std::endl;
    std::cout<<std::endl;
    std::cout<<"left shift: bool/unsigned int"<<std::endl;
    std::cout<<"false >> 0U = "<<bool(false >> 0U)<<std::endl;
    std::cout<<"false >> 1U = "<<bool(false >> 1U)<<std::endl;
    std::cout<<"false >> 2U = "<<bool(false >> 2U)<<std::endl;
    std::cout<<"false >> 100U = "<<bool(false >> 100U)<<std::endl;
    std::cout<<"true >> 0U = "<<bool(true >> 0U)<<std::endl;
    std::cout<<"true >> 1U = "<<bool(true >> 1U)<<std::endl;
    std::cout<<"true >> 2U = "<<bool(true >> 2U)<<std::endl;
    std::cout<<"true >> 100U = "<<bool(true >> 100U)<<std::endl;
    std::cout<<std::endl;
    std::cout<<"left shift: bool/int"<<std::endl;
    std::cout<<"false >> -100 = "<<bool(false >> -100)<<std::endl;
    std::cout<<"false >> -2 = "<<bool(false >> -2)<<std::endl;
    std::cout<<"false >> -1 = "<<bool(false >> -1)<<std::endl;
    std::cout<<"false >> 0 = "<<bool(false >> 0)<<std::endl;
    std::cout<<"false >> 1 = "<<bool(false >> 1)<<std::endl;
    std::cout<<"false >> 2 = "<<bool(false >> 2)<<std::endl;
    std::cout<<"false >> 100 = "<<bool(false >> 100)<<std::endl;
    std::cout<<"true >> -100 = "<<bool(true >> -100)<<std::endl;
    std::cout<<"true >> -2 = "<<bool(true >> -2)<<std::endl;
    std::cout<<"true >> -1 = "<<bool(true >> -1)<<std::endl;
    std::cout<<"true >> 0 = "<<bool(true >> 0)<<std::endl;
    std::cout<<"true >> 1 = "<<bool(true >> 1)<<std::endl;
    std::cout<<"true >> 2 = "<<bool(true >> 2)<<std::endl;
    std::cout<<"true >> 100 = "<<bool(true >> 100)<<std::endl;
    std::cout<<std::endl;
    return 0;
}

It produces the following output on my computer:

right shift: bool/bool
false << false = 0 // Well defined
false << true = 0 // Well defined
true << false = 1 // Well defined
true << true = 1 // Well defined

right shift: bool/unsigned int
false << 0U = 0 // Well defined
false << 1U = 0 // Well defined
false << 2U = 0 // ?
false << 100U = 0 // Undefined behaviour
true << 0U = 1 // Well defined
true << 1U = 1 // Well defined
true << 2U = 1 // ?
true << 100U = 0 // Undefined behaviour

right shift: bool/int
false << -100 = 0 // Undefined behaviour
false << -2 = 0 // Undefined behaviour
false << -1 = 0 // Undefined behaviour
false << 0 = 0 // Well defined
false << 1 = 0 // Well defined
false << 2 = 0 // ?
false << 100 = 0 // Undefined behaviour
true << -100 = 0 // Undefined behaviour
true << -2 = 0 // Well defined
true << -1 = 0 // Well defined
true << 0 = 1 // Well defined
true << 1 = 1 // Well defined
true << 2 = 1 // ?
true << 100 = 0  // Undefined behaviour

left shift: bool/bool
false >> false = 0 // Well defined
false >> true = 0 // Well defined
true >> false = 1 // Well defined
true >> true = 0 // Well defined

left shift: bool/unsigned int
false >> 0U = 0 // Well defined
false >> 1U = 0 // Well defined
false >> 2U = 0 // ?
false >> 100U = 0  // Undefined behaviour
true >> 0U = 1 // Well defined
true >> 1U = 0 // Well defined
true >> 2U = 0 // ?
true >> 100U = 0  // Undefined behaviour

left shift: bool/int
false >> -100 = 0  // Undefined behaviour
false >> -2 = 0  // Undefined behaviour
false >> -1 = 0  // Undefined behaviour
false >> 0 = 0 // Well defined
false >> 1 = 0 // Well defined
false >> 2 = 0 // ?
false >> 100 = 0  // Undefined behaviour
true >> -100 = 0  // Undefined behaviour
true >> -2 = 1  // Undefined behaviour
true >> -1 = 1  // Undefined behaviour
true >> 0 = 1 // Well defined
true >> 1 = 0 // Well defined
true >> 2 = 0 // ?
true >> 100 = 0  // Undefined behaviour

The C++ standard part 5.8 expr.shift describes the behaviour of the shift operator, but I want to be sure to understand it well. Consequently, I would like to know for each line I test, whether the line is "well defined behaviour and implementation independent", or whether it's "implementation dependent/undefined behaviour".

EDIT: I pre-filled it, so I just need a confirmation, and an answer about the case where I don't know (noted ? )

There are only a few cases to consider. We call E1 the promoted left operand and E2 the promoted right operand. The undefined behavior cases are:

  • If E2 "is negative, or greater than or equal to the length in bits of" E1
  • In E1 << E2 , if E1 is signed and either
    a. negative
    b.E1×2 E2 is not "representable in the corresponding unsigned type of the result type"

The implementation-defined behavior cases are:

  • In E1 >> E2 , if E1 "has a signed type and a negative value."

Everything else is well-defined.


Your cases marked with a ? are all well-defined. E1 and E2 are never negative, and E2 is nowhere near 32, so there's no concern for overflow. All are well-defined int s.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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