Search code examples
c++if-statementstandardsundefined-behavior

C++ "else" statement when the preceding line has multiple "if" statements


The following C++ program

#include <iostream>

int main() {
    for(int i=0; i<5; i++) for(int j=0; j<5; j++){
        if(i==1) if(j==2) std::cout << "A " << i << ' ' << j << std::endl;
        else std::cout << "B " << i << ' ' << j << std::endl;
    }
    return 0;
}

outputs

B 1 0
B 1 1
A 1 2
B 1 3
B 1 4

From this I infer that the "else" statement is referring to the second "if".

Is this behavior described in the C++ standard? Is there a reason for implementing it this way? I intuitively expected "else" to refer to the first "if".


Solution

  • There was an answer that tried to advocate adding braces. We can rearrange your code also without braces to see more clearly what it does (and why it is not doing what you intended):

    #include <iostream>
    
    int main() {
        for(int i=0; i<5; i++) for(int j=0; j<5; j++){
            if(i==1) 
                if(j==2) 
                    std::cout << "A " << i << ' ' << j << std::endl;
                else 
                    std::cout << "B " << i << ' ' << j << std::endl;
        }
        return 0;
    }
    

    The general syntax (see eg here) is:

    if ( condition ) statement-true
    

    In your case the whole

                if(j==2) 
                    std::cout << "A " << i << ' ' << j << std::endl; // [1]
                else 
                    std::cout << "B " << i << ' ' << j << std::endl; // [2]
    

    is the statement-true. While general if-else is:

    if ( condition ) statement-true else statement-false
    

    Hence, [1] is the statement-true and [2] is the statement-false of the inner if-else-statement.

    Intendation and lines do not matter, thats why it is advisable to always use braces:

            if(i==1) {
                if(j==2) { 
                    std::cout << "A " << i << ' ' << j << std::endl;
                } else {
                    std::cout << "B " << i << ' ' << j << std::endl;
                }
            }
    

    Or, if thats what you want:

            if(i==1) {
                if(j==2) { 
                    std::cout << "A " << i << ' ' << j << std::endl;
                }
            } else {
                std::cout << "B " << i << ' ' << j << std::endl;
            }
    

    Credits goes to acraig5075, this is basically just a reformulation of their (now deleted) answer.