Variable Scopes in C++

By , last updated September 12, 2017

Variables in every programming language are used to store values that can change the program.

Like other programming languages, C++ also provides different data types that can be used to declare variables to store different values like characters, decimals and integer values etc.

Data types available in C++ are int, char, bool, float, double, short and long.

Scope of a Variable

Every variable in C++ has a specific area of functioning, in which that particular variable can be called and used. Out of that specific area variables don’t hold their value and can’t be used.

This specific area in which a variable holds its value and can be used is called scope of a variable.

Variables in C++ are of following two types and so is the scope associated with them: local and global.

Local Variables

The local variables are the ones that are created inside curly brackets {} within a function or a block. The scope of a local variable is limited to curly brackets in which they are declared and can’t be used outside these curly brackets.

Let’s have a look at a simple example to understand the concept of a scope of a local variable:

int main()
{
	int weight  = 65, length  = 98, speed = 23;
	cout << "weight of fish = " << weight << endl;
	cout << "Length of road " << length << endl;
	cout << "speed of car = " << speed  << endl;
	return 0;
}

In the above example, three variables weight, length and speed are created and initialized, the type of all of these three variables is int. They all are created and initialized inside the main function and can be used only between curly brackets that start after the main function.

Let’s have a look at another example of a local variable within a block:

int main()
{
	int temp=110;
	if(temp<20)        		// if condition scope starts here
	{
		int ValueK=100;   	// A Local variable  has been declared and initialized
	}	                    // if condition scope ends here
	cout << ValueK;     
}

If you run the above program you will get a compile time error, since you are trying to access the variable ‘ValueK’ outside its scope. The scope of ‘ValueK’ is limited only within the curly brackets that start after the if condition in the above program.

Local variable is referenced before assignment

If C++ local variable is referenced before assignment, it will run OK in case of strings, but will fail with an “uninitialized local variable used” exception (if it’s enabled during runtime). A decent compiler will trigger a warning when it detects use of an uninitialized variable (default initialized).

The reason why string works OK, is because it’s not a “POD” (Plain Old Data) type. A string will be constructed and the default initialized state is a well defined one.

This example will produce a runtime error for variables a, b, c and d:

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

int main()
{
	string hello;
	int a;
	double b;
	float c;
	bool d;

	cout << "Not init: " << hello << ", " << a << ", " << b << ", " << c << ", " << d;

	hello = "Hello, World!";
	a = 1;
	b = 1.0;
	c = 1.0;
	d = true;

	cout << "\nInit: " << hello << ", " << a << ", " << b << ", " << c << ", " << d;
	
	return 0;
}

This code will run fine and produce an output “Hello, World!”:

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

int main()
{
	string hello;

	cout << hello;

	hello = "Hello, World!";

	cout << hello;
	
	return 0;
}

Access local variable outside of it’s scope

Accessing local variables outside of their scopes is not allowed in almost all languages. Although in C++ you may actually access the memory of the local variable from within other methods.

Warning: accessing memory of local variables is a dangerous thing!

Here is an example of a code where accessing a memory of a local variable may go well:

int * foo()
{
	int a = 1;
	return &a;
}

int main()
{
	int* b = foo();
	cout << *b; // may print 1
	*b = 2;
	cout << *b; // may print 2
}

This code will produce the result “12”. The local variables live on stack and the value of a local variable a from the method foo is not yet “popped” from stack when we try to print its value.

If you initialize another local variable c and try to access our first variable a after accessing the new variable c the value will be “lost”:

int * foo()
{
	int a = 1;
	return &a;
}

int main()
{
	int* b = foo();
	int c = 3;
	cout << ", " << *&c <<", ";
	cout << *b;
	*b = 2;
	cout << *b;
}

This modified code may produce: ” , 3, “.

Using temporary variables, who are out of scope, will most likely cause the program to crash or behave in an unsuspecting way. If it “works” with one compiler, it may not work tomorrow or with other compilers.

Global Variables

Global variables differ from the local variables in a sense that they are declared outside of all functions. Their scope is a full file in which they are declared. An example can better illustrate the concept:

int speed;	// This is global variable (only declared not initialized)
int main()
{
	speed =  30; 		// Global variable initialized with value
	cout  << "Speed of car " << speed  << endl;
	return 0;
}

In the above example, integer variable ‘speed’ is a global variable and is declared outside the main function. This variable can be used in any function that is created inside this file. Global variables, unlike local variables are available in every function to use.

C++ variables with the same name

If you are passing a local variable into another method and use the same name, the program won’t compile and will give you “redefinition of formal parameter” exception.

Here is a simple example that won’t compile:

void foo(int a)
{
	int a = 2;
	cout << a;
}

int main()
{
	int a = 1;
	foo(a);
}

Local and Global variables with the same name

If you have a local and a global variables with the same name within the same function, local variables will always “win” or shadow the values of global variables.

Here is a C++ class example with local and global variables with the same name:

#include <iostream>
using namespace std;
class Foo {
	int a = 1;

public:
	void bar()
	{
		int a = 2;
		cout << a;
	}
};

Foo foo;
int main()
{
	foo.bar();
}

This program will print “2”.

Variable initialization

Local C++ variables are not initialized per default, if they are “Plain Old Data”. Global variables is initialized to 0:

C++ Data Types Default Values
int,short,long 0
char 0
bool 0
double/float 0

Here is a simple C++ program to check default global values:

class Foo {
	int a;
	short b;
	char c;
	long d;
	bool e;
	double f;
	float g;

public:
	void bar()
	{
		cout << a <<"\n";
		cout << b << "\n";
		cout << c << "\n";
		cout << d << "\n";
		cout << e << "\n";
		cout << f << "\n";
		cout << g << "\n";
	}
};

Foo foo;

int main()
{
	foo.bar();
}

Pay attention to warnings when compiling

We had two methods stop() and remove(). In stop, remove is called with an async parameter.

void remove(bool async)
{
    /* do stuff*/
}

void stop()
{
    bool async = false,
    remove(async);
}

We couldn’t figure out why my method wasn’t being called, until we recompiled the file and saw this warning:

warning C4189: 'remove' : local variable is initialized but not referenced

Then it was pretty clear what we’d miss: on our keyboard layout, comma and semicolon is on the same key, separated by pressing shift.

Comments

Be the first to comment.

Leave a Reply


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*