Search

1.3 — A first look at variables, initialization, and assignment

Objects

C++ programs create, access, manipulate, and destroy objects. An object is a piece of memory that can be used to store values. You can think of an object as a mailbox, or a cubbyhole, where we can store and retrieve information. All computers have memory, called RAM (random access memory), that is available for programs to use. When an object is defined, a piece of that memory is set aside for the object.

Most of the objects that we use in C++ come in the form of variables.

Variables

A statement such as x = 5; seems obvious enough. As you might guess, we are assigning the value of 5 to x. But what exactly is x? x is a variable.

A variable in C++ is simply an object that has a name.

In this section, we are only going to consider integer variables. An integer is a number that can be written without a fractional component, such as -12, -1, 0, 4, or 27. An integer variable is a variable that holds an integer value.

In order to create a variable, we generally use a special kind of declaration statement called a definition (we’ll explain the precise difference between a declaration and a definition later). Here’s an example of defining variable x as an integer variable (one that can hold integer values):

When this statement is executed by the CPU, a piece of memory from RAM will be set aside (called instantiation). For the sake of example, let’s say that the variable x is assigned memory location 140. Whenever the program sees the variable x in an expression or statement, it knows that it should look in memory location 140 to get the value.

One of the most common operations done with variables is assignment. To do this, we use the assignment operator, more commonly known as the = symbol. For example:

When the CPU executes this statement, it translates this to “put the value of 5 in memory location 140”.

Later in our program, we could print that value to the screen using std::cout:

l-values and r-values

In C++, variables are a type of l-value (pronounced ell-value). An l-value is a value that has a persistent address (in memory). Since all variables have addresses, all variables are l-values. The name l-value came about because l-values are the only values that can be on the left side of an assignment statement. When we do an assignment, the left hand side of the assignment operator must be an l-value. Consequently, a statement like 5 = 6; will cause a compile error, because 5 is not an l-value. The value of 5 has no memory, and thus nothing can be assigned to it. 5 means 5, and its value can not be reassigned. When an l-value has a value assigned to it, the current value at that memory address is overwritten.

The opposite of l-values are r-values (pronounced arr-values). An r-value refers to values that are not associated with a persistent memory address. Examples of r-values are single numbers (such as 5, which evaluates to 5) and expressions (such as 2 + x, which evaluates to the value of variable x plus 2). r-values are generally temporary in nature and are discarded at the end of the statement in which they occur.

Here is an example of some assignment statements, showing how the r-values evaluate:

Let’s take a closer look at the last assignment statement above, since it causes the most confusion.

In this statement, the variable x is being used in two different contexts. On the left side of the assignment operator, “x” is being used as an l-value (variable with an address) in which to store a value. On the right side of the assignment operator, x is evaluated to produce a value (in this case, 7). When C++ evaluates the above statement, it evaluates as:

Which makes it obvious that C++ will assign the value 8 back into variable x.

For the time being, you don’t need to worry about l-values or r-values much, but we’ll return to them later when we start discussing some more advanced topics.

The key takeaway here is that on the left side of the assignment, you must have something that represents a memory address (such as a variable). Everything on the right side of the assignment will be evaluated to produce a value.

Initialization vs. assignment

C++ supports two related concepts that new programmers often get mixed up: assignment and initialization.

After a variable is defined, a value may be assigned to it via the assignment operator (the = symbol):

C++ will let you both define a variable AND give it an initial value in the same step. This is called initialization.

A variable can only be initialized when it is defined.

Although these two concepts are similar in nature, and can often be used to achieve similar ends, we’ll see cases in future lessons where some types of variables require an initialization value, or disallow assignment. For these reasons, it’s useful to make the distinction now.

Rule: When giving variables an initial value, favor initialization over assignment.

Uninitialized variables

Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location! A variable that has not been given a known value (through initialization or assignment) is called an uninitialized variable.

Note: Some compilers, such as Visual Studio, will initialize the contents of memory when you’re using a debug build configuration. This will not happen when using a release build configuration.

Using the values of uninitialized variables can lead to unexpected results. Consider the following short program:

In this case, the computer will assign some unused memory to x. It will then send the value residing in that memory location to std::cout, which will print the value. But what value will it print? The answer is “who knows!”, and the answer may change every time you run the program. When the author ran this program with the Visual Studio 2013 compiler, std::cout printed the value 7177728 one time, and 5277592 the next.

If you want to run this program yourself, make sure you’re using a release build configuration (see section 0.6a -- Build configurations for information on how to do that). Otherwise the above program may print whatever value your compiler is initializing memory with (Visual Studio uses -858993460).

If your compiler won’t let you run this program because it flags variable x as an uninitialized variable, here is a possible solution to get around this issue:

Using uninitialized variables is one of the most common mistakes that novice programmers make, and unfortunately, it can also be one of the most challenging to debug (because the program may run fine anyway if the uninitialized value happened to get assigned to a spot of memory that had a reasonable value in it, like 0).

Fortunately, most modern compilers will print warnings at compile-time if they can detect a variable that is used without being initialized. For example, compiling the above program on Visual Studio 2005 express produced the following warning:

c:vc2005projectstesttesttest.cpp(11) : warning C4700: uninitialized local variable 'x' used

A good rule of thumb is to initialize your variables. This ensures that your variable will always have a consistent value, making it easier to debug if something goes wrong somewhere else.

Rule: Make sure all of your variables have known values (either through initialization or assignment).

Undefined behavior

Using the value from an uninitialized variable is our first example of undefined behavior. Undefined behavior is the result of executing code whose behavior is not well defined by the language. In this case, the C++ language doesn’t have any rules determining what happens if you use value of a variable that has not been given a known value. Consequently, if you actually do this, undefined behavior will result.

Code implementing undefined behavior may exhibit any of the following symptoms:

  • Your program produces an incorrect result consistently.
  • Your program produces different results every time it is executed.
  • Your program behaves inconsistently (sometimes produces the correct result, sometimes not).
  • Your program seems like its working but produces incorrect results later in the program.
  • Your program crashes, either immediately or later.
  • Your program works on some compilers but not others.
  • Your program works until you change some other seemingly unrelated code.

Or, your code may actually produce the correct behavior anyway. The nature of undefined behavior is that you never quite know what you’re going to get, whether you’ll get it every time, and whether it’ll change when you make other changes.

C++ contains many cases that can result in undefined behavior if you’re not careful. We’ll ensure we point these out in future lessons. Take note of where these cases are and make sure you avoid them.

Rule: Take care to avoid situations that result in undefined behavior.

Author’s note: One of the most common types of comment we get from readers says, “You said I couldn’t do X, but I did it anyway and my program works! Why?”. The answer is almost always that your program is actually exhibiting undefined behavior, but that undefined behavior just happens to be producing the result you wanted anyway… for now. Tomorrow it might not.

Alternatively, sometimes compiler authors take liberties with the language requirements when those requirements may be more restrictive than needed. For example, the standard may say, “you must do X before Y”, but a compiler author may feel that’s unnecessary, and make Y work even if you don’t do X first. This shouldn’t affect the operation of correctly written programs, but may cause incorrectly written programs to work anyway. So an alternate answer to the above question is that your compiler may simply be not following the standard! It happens.

Quiz

What values does this program print?

6) What is undefined behavior?

Quiz Answers

To see these answers, select the area below with your mouse.

1) Show Solution

2) Show Solution

3) Show Solution

4) Show Solution

5) Show Solution

6) Show Solution

.

1.3a -- A first look at cout, cin, and endl
Index
1.2 -- Comments

300 comments to 1.3 — A first look at variables, initialization, and assignment

  • jimin

    At first i assigned x by 5 and then it gave me 3, but when i replaced 5 by 6 it still gave me answer 3. Can so explain that for me ?
    #include <iostream>
    int main()
    {int x = 5; x = x - 2;std :: cout << x;
        return 0;}

    • Hi Jimin!

      Make sure you compile the program before running it. In most cases the button to compile is a hammer symbol. Some IDEs don't compile the code automatically before running it, except for the first run.

  • ishan

    How to disable compiler extensions for Code blocks?

    • Alex

      You can disable compiler extensions for Code::Blocks via Settings menu->Compiler->Compiler flags tab, then find and check the “-pedantic” option.

  • alok

    Why am I getting a 0 when I have compile and run the following code. I am compiling using `cl /EHsc /W4 Uninitialized.cpp`

    <code>
      #include <iostream>

      int main()
      {
        int x;
        std::cout << x;

        return 0;
    }
    </code>

  • John Mosquera

    Thanks for doing and maintaining this guide - I did some testing
    I ran the uninitialized variables programme using Code::Blocks
    std::cout printed the value 4354190 with an execution time :0.292 s (I wonder if my computer is slow)
    A few minutes later I ran it again and printed the same number but faster 0.047 s
    Running it more times with the same printed value and same speed of 0.047 s
    But if I add a blank space to the code and press the build button and run it prints the same number but slower 0.281 s
    Further executions are again 0.047 s
    I now I press build (without adding blank spaces), press build and run with 0.043 s (faster than the norm)
    and run again, it goes to the same 0.047 s
    By removing // comments and some white space, build and run, it went down to 0.031 s (the fastest)
    running again it goes to the same 0.047 s and value remained the same as 4354190 (I may try again at a later date to see if it changes).
    Oops, apologies for my long comments, I got too carried away and went OTT. Thanks

    • Alex

      I'm guessing it has to do with caching -- the first execution of a new program requires loading the program into memory, whereas for subsequent executions it may already be in memory.

  • Haitam

    Wow people still comment here ?

    • Kyle

      reason why is likely people are finding out relying only on apps suck and want to program their own stuff as the "software" industry is shell of it's former self and thinks all you want are apps you rent...  

      Only games are being done on 2,000$ PC's and most are console ports usually crappy reading funny reviews on Steam.  Walk into any store in 2005 and there were GOBS of software of all sorts not just violent games or even games at all!  now you search for software for windows 10 all you get is basic OS maintenance stuff.  same at Office depot boooooooooooooring.

      those who grew up on this tried to gert some of it working thru virtual machines but thet are developed for businesses only like running old server stuff using a Pentium 1  NOT consumer products if it works it's more down to luck then design.

  • Hi Alex!

    "On Visual Studio, you can do this setting is found in"
    I think that should be
    "In Visual Studio, this setting is found in".

  • Nguyen

    Hi,

    Could you please let me know why line 10 gives me an error?

    Thanks

  • Jan Williams

    I got the answers to the quiz correct from reading through them but when I decided it might be fun and good practice to try and put them in Visual Studio I only got the first one to work.  Can you give me a screen shot of what the second one would look like in Visual Studio so I can see what I'm doing wrong? Maybe I can get 3 to work.  (I'm not going to enter 5 or 6).

  • Adrian

    I tried the snippet code for printing the uninitialized integer variable. when I tried the function with an int argument visual C++ gives me error but when I changed it to &argument it's worked fine!
    I know that & operator pass location of variable to function but I don't get it what's happened here.

    // #include "stdafx.h" // Uncomment if Visual Studio user
    #include <iostream>

    void doNothing(int x)    //instead of const int &x I used int x and the file failed to compile
    {
    }

    int main()
    {
        // define an integer variable named x
        int x; // this variable is uninitialized

        doNothing(x); // make compiler think we're using this variable

        // print the value of x to the screen (dangerous, because x is uninitialized)
        std::cout << x;

        return 0;
    }

    • Alex

      When the function parameter is int x, this is a pass by value, so the argument (main's x) is _copied_ into doNothing's x. Therefore the argument isn't changed by the function, and smart compilers will detect this and show an error about using an undefined variable.

      When the function parameter is int &x, this is a pass by reference (covered in a later chapter). In this case, doNothing's x is an alias to the x that main is passing as an argument, so anything doNothing does to x affects the argument. Even though doNothing() doesn't change the argument, most compilers aren't smart enough to realize this, so they disable the error because they can't definitively conclude that x hasn't been assigned a value somewhere along the way.

  • Izak

    Typo: "an known value."
    I think it should be "a known value."

  • Jack

    Am I Right? Short Recap.

    an integer (int) is a number that can be written without a fractional component such as -12 0 or 109.

    an integer works this way.

    int x; //you gotta tell the compiler its an integer before assigning a value to the integer.
    x = 5; // this is the value ive chosen to give my integer

    cout << x <<endl; //notice that i didnt put colons? Thats because your printing a value of another variable otherwise it would say x!

    • nascardriver

      Hi Jack!

      > an integer (int) is a number that can be written without a fractional component such as -12 0 or 109.
      Correct

      Prefer initialization over assignment. If you can't initialize a variable to the correct value initialize it to 0 or equivalent.

      > notice that i didnt put colons?
      This is a colon :, if mean an single quotation mark you're right.

  • Everything is going smoothly so far.
    You guys did a great job by putting up a quiz at the end!
    It definitely makes it feel like I'm doing this at school. I've been hooked for hours, I'm not sure if I'll be able to sleep, haha:-D.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]