2

I am confused about variable scope and would like to better understand it.

Moved cout oddS and cout evenS to outside for loop. Code executes properly. If moved inside for loop, code executes with improper values for oddS and evenS.

#include <iostream>
#include <vector>
#include <cmath>

int main()
{
    double evenS, oddS, pH = 0;
    std::vector<double> v1 = {2, 4, 3, 6, 1, 9};

    for(int i = 0; i < v1.size(); i++)
    {
        pH = v1[i];
        if(fmod(pH, 2) == 0)
        {
          evenS = evenS + v1[i];
        }
        else if(fmod(pH, 2) == 1)
        {
          oddS = oddS + v1[i];
        }
    }

    std::cout << evenS << "\n";
    std::cout << oddS << "\n";
}

I was expecting the oddS and evenS to not hold the proper values if incremented outside of the for loop. However, the contrary is true, which produced my confusion.

zmike
  • 1,090
  • 10
  • 24
wiregh0st
  • 57
  • 10
  • 1
    It would be easier if you could illustrate the scopes by formatting the brackets correctly. Indentations are inputted via the TAB key. Each new bracket is one TAB in. – DeiDei Jun 27 '19 at 14:07

3 Answers3

5

Your code has Undefined Behaviour (it contains a bug), which means it can do literally anything. It makes little sense to try to analyse why moving statements around changes output, or how [counter-]intuitive they are.

The problem is in the fact that your variables evenS and oddS are not initialised, and you're reading their values before writing to them. Reading an uninitialised value is UB.

You probably meant to write this as the definition:

double evenS = 0, oddS = 0, pH = 0;

Each variable being declared in a declaration needs its own initialiser if it is to have one.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thanks for your explanation. I have refined this bit of code to initialize the variables properly. I will make sure to use this in the future. My question arose from moving the cout statements on oddS and evenS up one bracket. I was under the impression that if I make changes to these variables within the for statement, then cout the variable(s) outside of the for, they would not output the correct values. Maybe I am getting this confused with how a function returns values though. I believe I have it figured out now. Thanks for your time. – wiregh0st Jun 27 '19 at 14:49
  • @wiregh0st A variable retains its value during its entire lifetime (from creation/initialisation to desctruction), even if control flow enters (and subsequently leaves) other scopes in the meantime. – Angew is no longer proud of SO Jun 27 '19 at 14:54
  • 1
    @wiregh0st _"I was under the impression that if I make changes to these variables within the for statement, then cout the variable(s) outside of the for, they would not output the correct values."_ No. The variable is either in scope or it isn't. Its values don't evaporate when you hit an unrelated `}`. _"Maybe I am getting this confused with how a function returns values though"_ Same story there – Lightness Races in Orbit Jun 27 '19 at 14:54
0

As @Angew mentioned, you have a bug in your code and he suggested a fix. The following topic is helpful to understand uninitalized values: What happens to a declared, uninitialized variable in C? Does it have a value?

As for variable scope, if you bring std::cout << evenS << "\n"; and std::cout << oddS << "\n"; into the loop, the values of evenS and oddS would be printed more frequently.

zmike
  • 1,090
  • 10
  • 24
-2

Here's an explanation of scope from Tutorials Point (annotations in square brackets):

A scope is a region of the program and broadly speaking there are three places, where variables can be declared −

  1. Inside a function or a block which is called local variables. [Here block means a portion of code starting and ending on these brackets {}]
  2. In the definition of function parameters which is called formal parameters.
  3. Outside of all functions which is called global variables.

Local Variables

Variables that are declared inside a function or block are local variables. They can be used only by statements that are inside that function or block of code. [if you try to access outside either compiler will give you an error.]

Global Variables

Global variables are defined outside of all the functions, usually on top of the program. The global variables will hold their value throughout the life-time of your program.

Now in your case as you said

Moved cout oddS and cout evenS to outside for loop. Code executes properly. If moved inside for loop, code executes with improper values for oddS and evenS.

If you declare variable inside for loop, its scope will remain within that block (within that loop).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Asad Ali Choudhry
  • 4,985
  • 4
  • 31
  • 36
  • 2
    Not true. If the variable were out of scope, attempting to read from it would _fail to compile_, not "print some garbage value". – Lightness Races in Orbit Jun 27 '19 at 14:33
  • 1
    The rest of the answer is just an irrelevant copy/paste from another webpage – Lightness Races in Orbit Jun 27 '19 at 14:34
  • Yes my mistake garbage should not print, I edited my answer – Asad Ali Choudhry Jun 27 '19 at 14:41
  • its not fully copied, I modified it to explain, and even I mentioned the reference as well, thats why you are down voting it, as I mentioned the reference? :) worst. – Asad Ali Choudhry Jun 27 '19 at 14:42
  • 1
    Oh yes you did add two little annotations. But you cannot take someone else's words and pass them off as your own. That is not okay. The _only_ original work in the answer was incorrect, in the manner that I already explained, hence the downvote. The current form of this answer is no longer technically incorrect, but is still unsubstantive. "its scope will remain within that block" How does that answer the question? It does not address the problem at all. – Lightness Races in Orbit Jun 27 '19 at 14:53