#include // The following program compiles, but there are // inputs for which it prints the wrong result. // // First, try several inputs and determine which // inputs cause the program to produce an incorrect // result. Then identify and fix the bug. // // Try to find the bug before reading the explanation // below. // Function declarations int main(); // Function definitions int main() { int n{}; std::cout << "Enter an integer: "; std::cin >> n; int result{ n }; if ( n < 0 ) { int result{ -n }; } std::cout << "The absolute value of " << n << " is " << result << std::endl; return 0; } // Explanation: // // The program works correctly when n >= 0, but it // produces the wrong result whenever n < 0. // // The problem is that 'result' is declared twice. // // First, it is declared in the body of main(): // // int result{ n }; // // A second local variable with the same name is then // declared inside the block of the if statement: // // if ( n < 0 ) { // int result{ -n }; // } // // These are two different local variables. // // Inside the block, the second 'result' shadows the // first 'result'. Thus, while executing that block, // the identifier 'result' refers to the variable // declared inside the block. // // That variable is correctly initialized to -n, but // it ceases to exist when execution reaches the end // of the block. // // The original 'result' was never changed. Therefore, // after the block, it still contains its original // value of n. // // The solution is not to declare another variable // named 'result'. Instead, assign -n to the variable // that was already declared. // Here is the corrected program: /* int main() { int n{}; std::cout << "Enter an integer: "; std::cin >> n; int result{ n }; if ( n < 0 ) { result = -n; } std::cout << "The absolute value of " << n << " is " << result << std::endl; return 0; } */ // If this is still confusing, consider how the // compiler treats the two declarations. // // Despite containing exactly the same characters, // the two occurrences of the identifier 'result' // refer to different local variables while inside // the block. // // We could rename the variable declared inside the // block without changing what the program does: // // int main() { // int n{}; // // std::cout << "Enter an integer: "; // std::cin >> n; // // int result{ n }; // // if ( n < 0 ) { // int douglas_adams{ -n }; // } // // std::cout << "The absolute value of " // << n << " is " // << result << std::endl; // // return 0; // } // // It should now be clear that 'result' is never // changed when n < 0. The variable 'douglas_adams' // is initialized and then immediately ceases to // exist. // // Declaring a local variable with the same name as // another local variable that is still in scope is // called shadowing. Although C++ permits shadowing, // it can make programs more difficult to understand // and, as this example demonstrates, can easily // introduce bugs.