0

I am practice with C++ and I see some problem:

#include <iostream>
#include <string>
using namespace std;

int main() {
    int a = 2;
    {
        cout << a;
        cout << "\n";
        float a = a / 2;
        cout << "a= a/2 = ";
        cout << a;

    }
    cout << "\n";
    a = 2;
    {
        cout << a;
        cout << "\n";
        float b = a / 2;
        cout << "b= a/2 = ";
        cout << b;

    }
}

This return:

2 
a= a/2 = 0 
2 
b= a/2 = 1

I want to know why a = a/2 = 0 ?

Thank you

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    Please don't tag C++ questions as C as well. Also try and trim off any debris in your code so we can just compile it as-is instead of having to bash around and delete a bunch of junk. – tadman Sep 23 '20 at 04:18
  • 4
    That shouldn't even compile, you can't define the variable `a` twice with two different types. – Mark Ransom Sep 23 '20 at 04:18
  • 8
    This looks like undefined behaviour since you're shadowing `a` with a whole new, unrelated `a`. – tadman Sep 23 '20 at 04:19
  • 1
    The `{}` create a new scope with a separate `a` variable. There is nothing undefined about the behaviour. It's just unusual - but permitted - to use plain `{}` to create a new scope without any `for`/`if`/`while`/etc. – Karl Knechtel Sep 23 '20 at 04:21
  • 3
    The undefined bit is `a` is used unitialized in `float a = a / 2;` `a / 2` uses `float a`, which has no value yet, not `int a`. – user4581301 Sep 23 '20 at 04:24
  • why does the outer scope ```a``` get printed using ```cout```? –  Sep 23 '20 at 04:25
  • 2
    @fardinho21 The outer scope `a` is still visible until replaced by the definition of `float a`. – user4581301 Sep 23 '20 at 04:29

2 Answers2

7

This is a subtle error. Look at this code:

int a = 2;
{
    float a = a / 2;
}

Outside of the curly braces, the name a refers to int a, the integer declared up top. But inside the curly braces, once you reach the line in which float a is declared, the name a refers to float a inside the braces rather than int a outside the braces.

This is a problem because the line

float a = a / 2;

means "create a new variable named a of type float. Oh, and it needs an initial value. That's okay! Give it the value of float a, divided by two." See the problem here? The variable a is being initialized in terms of itself, so when a / 2 is computed a has not been initialized and the results are undefined.

To fix this, simply give float a a new name.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    Would it be worth mentioning that with your reduced code sample, you could comment out `int a = 2;` and still compile? – JaMiT Sep 23 '20 at 05:02
2

Because you are actually using declared, but never initialized variable when you stated float a = a/2. My computer prints 4.49985e-039 but that could be any number.
You are confusing yourself because you have two int & float variable with same name. Better to choose your name of the variable carefully or you have to track your code to see which is indicating which.
I'll comment on the each line which variable a has been used.

#include <iostream>
#include <string>
using namespace std;

int main() {
  int a = 2;  // int a declared in main scope used;
  {
    cout << a;  // int a declared in main scope; since there is no a declared in local scope.
    cout << "\n";
    float a = a/2; // block scope variable a used without initialization to initialize itself. UB. 
    cout << "a= a/2 = ";  // block scope variable used
    cout << a;  // block scope variable used
  }
  cout << "\n";   a = 2;  // int a declared in main scope; Since it's block scope is within main scope only.
  {
    cout << a;  // int a declared in main scope; since no a has been declared in local scope
    cout << "\n";
    float b = a/2; // int a declared in main scope; since no a has been declared in local scope
    cout << "b= a/2 = "; // int a declared in main scope; since no a has been declared in local scope
    cout << b;
  }
}
Lazy Ren
  • 704
  • 6
  • 17
  • 1
    @user4581301 good point. Thank you. I've edited my answer. – Lazy Ren Sep 23 '20 at 04:35
  • I cringe when I see "obviously". Would you consider something more like "the only option here"? – JaMiT Sep 23 '20 at 05:05
  • @JaMiT Sorry if my usage of word felt somewhat offensive. English is not my first language so I might have used word in a way that I did not intended. I've changed the term. – Lazy Ren Sep 23 '20 at 05:43
  • "Offensive" is inaccurate, and you did use "obviously" correctly. The problem is that there are many people who use "obviously" *in*correctly. They use "obviously" to mean *"I need this to be true, but I don't know why it is true, so I hope no one questions it."* It's good to distinguish yourself from those people. ;) – JaMiT Sep 25 '20 at 02:08