Introduction to Variables

A variable is a named location in memory used to store data while a program runs. Variables allow programs to remember values, perform calculations, and make decisions based on input or stored data.

Why Do I Need Variables?

In any non-trivial program, you're going to need a way to store and reference data. For example, in this course’s employee database project, we need to store information like employee names, addresses, and the number of hours they’ve worked. Each of these will be stored in a variable.

Without variables, a program wouldn't be able to retain or modify information while it runs.

Variable Names

When we make a variable, we need to it a name. It's important to choose a name that describes the purpose of the variable. When coding, always remember future you. Will future you be able to understand what the variable does, or why the variable exists? Pick a meaningful name.

Variable Types

In programming languages, we need to inform the compiler what the type of the variable is. The variable type tells the compiler the size of the memory to be stored, and the properties that memory has. The type is determined by what operations will happen to the memory. For example, an "age" should be stored in a number, which in C is an int.

Variable Declarations in C

In C, a variable must be declared before it can be used. A declaration specifies the variable's type (what kind of data it will hold), its name, and optionally its initial value.

type name = initial_value;

This line creates a variable of a given type, gives it a name, and sets an initial value.

Example:

int numTimesCalled = 0;
  • int is the type (an integer).
  • numTimesCalled is the name of the variable.
  • 0 is the initial value stored in that variable.

Best Practices for Naming Variables

Use meaningful names that describe what the variable represents. This helps you and others understand the code later. Avoid meaningless names like x or temp unless they are used in a very short and specific context.

Good:

int numTimesCalled;

Bad:

float x;

Summary

Variables are essential in any program. In C, you declare variables by specifying a type, name, and optionally an initial value. Understanding how to use and name them correctly is one of the first steps in writing clean, functional C code.


Variable Types

It's really important to understand the various types of variables that are available to you, as well as the modifiers for them and the minimum and maximum values they can contain

Types

Here are the common types, their bit length, their signedness, and the associated size.

  • C Data Type: char
    • Signed/Unsigned: Signed
    • Bit Length: 8 bits
    • Minimum Value: -128
    • Maximum Value: 127
  • C Data Type: unsigned char
    • Signed/Unsigned: Unsigned
    • Bit Length: 8 bits
    • Minimum Value: 0
    • Maximum Value: 255
  • C Data Type: short
    • Signed/Unsigned: Signed
    • Bit Length: 16 bits
    • Minimum Value: -32,768
    • Maximum Value: 32,767
  • C Data Type: unsigned short
    • Signed/Unsigned: Unsigned
    • Bit Length: 16 bits
    • Minimum Value: 0
    • Maximum Value: 65,535
  • C Data Type: int
    • Signed/Unsigned: Signed
    • Bit Length: 16 or 32 bits
    • Minimum Value: -2,147,483,648 (32-bit)
    • Maximum Value: 2,147,483,647 (32-bit)
  • C Data Type: unsigned int
    • Signed/Unsigned: Unsigned
    • Bit Length: 16 or 32 bits
    • Minimum Value: 0
    • Maximum Value: 4,294,967,295 (32-bit)
  • C Data Type: long
    • Signed/Unsigned: Signed
    • Bit Length: 32 bits
    • Minimum Value: -2,147,483,648
    • Maximum Value: 2,147,483,647
  • C Data Type: unsigned long
    • Signed/Unsigned: Unsigned
    • Bit Length: 32 bits
    • Minimum Value: 0
    • Maximum Value: 4,294,967,295
  • C Data Type: long long
    • Signed/Unsigned: Signed
    • Bit Length: 64 bits
    • Minimum Value: -9,223,372,036,854,775,808
    • Maximum Value: 9,223,372,036,854,775,807
  • C Data Type: unsigned long long
    • Signed/Unsigned: Unsigned
    • Bit Length: 64 bits
    • Minimum Value: 0
    • Maximum Value: 18,446,744,073,709,551,615
  • C Data Type: float
    • Bit Length: 32 bits
    • Minimum Value: ~ -3.4 x 10^38
    • Maximum Value: ~ 3.4 x 10^38
  • C Data Type: double
    • Bit Length: 64 bits
    • Minimum Value: ~ -1.7 x 10^308
    • Maximum Value: ~ 1.7 x 10^308

What Is Memory?

Computer memory (RAM) is where a running program stores data.

Examples of things stored in memory:

  • variables
  • program instructions
  • temporary calculations
  • user input

You can think of memory as a very large list of numbered boxes.

Address     Content
-------     -------
0x0001      00000000
0x0002      00000000
0x0003      00000000
0x0004      00000000

Each box stores a small piece of information.

Each box has an address, which is how the CPU finds it.

When you create a variable in a program, the compiler asks the operating system for space in memory.

Example:

int x = 5;

The computer might store it like this:

Address      Data
0x1000       00000000
0x1001       00000000
0x1002       00000000
0x1003       00000101
  • the variable x occupies 4 bytes
  • the number 5 is stored as binary

This process is what we mean by storing a value in memory.

What Is a Bit?

A bit is the smallest unit of information a computer can store.

A bit can only have two possible values:

0 1

These represent two electrical states in hardware:

  • 0 → off / low voltage
  • 1 → on / high voltage

So a bit is essentially a tiny on/off switch.

A single bit cannot represent many numbers because it only has two possibilities.

What Is a Byte?

A byte is a group of 8 bits.

Example of one byte(1 byte = 8 bits):

01010101

Bytes are the basic unit used to measure memory.

Examples:

MemorySize
1 byte8 bits
1 KB1024 bytes
1 MB1024 KB
1 GB1024 MB

Why Bits Matter

The number of bits determines how many values a variable can store.

Number of values = 2^(number of bits)

Examples:

BitsPossible Values
1 bit2
2 bits4
4 bits16
8 bits256
16 bits65,536
32 bits4,294,967,296

Signed vs Unsigned Numbers

Signed

Signed numbers can be:

  • negative
  • zero
  • positive

Example with 8 bits:

-128 → 127

Part of the bits are used to represent the sign.

Example conceptually:

0xxxxxxx = positive
1xxxxxxx = negative

Unsigned

Unsigned numbers cannot be negative.

All bits are used for positive numbers.

Example with 8 bits:

0 → 255

Because none of the bits are used for negative values.

Quick Comparison

TypeRange (8 bits)
signed-128 → 127
unsigned0 → 255

Unsigned numbers allow larger positive values, but cannot represent negative numbers.


What is scope?

When we declare variables in programming, those variables are only around for a certain period of time. They are stored in RAM, and as a result do not exist forever. The "scope" of a variable determines how long it lives, and more importantly as a programmer, where that variable can be accessed from.

Scope is a region in a program that is able to access a particular variable or set of variables in memory.

Why do I need to know about scope?

Variable scope in C affects what parts of the code can access our variables, and will eventually inform how we structure our program.

How does variable scope work in C?

In C, there are two primary types of scope. Local and Global scope.

Local Scope (Function Scope)

Local Scope is defined by the region inside of the parenthesis of a function, and defines where the program can access variables. For example, here we define a variable called personID. Because personID is declared within mainpersonID can later be modified in that function. The variable is "in scope."

int main()
{
    int personID = 0;
    personID += 1;
}

If we were to try and access the function personID outside of main, the program would throw an error.

With a functions local scope, we can also create regions of sub-scope where we can create additional variables that cannot be affected by the outside scope.

int main()
{
    int personID = 0;
    personID += 1;
    {
        // this will not affect the other personID
        int personID = 0;
    }
}

Global Scope

When a variable is declared outside of the confines of a function, all regions of code can touch that variable. Because everyone can access it, that variable is in global scope.

int g_NumPersons = 0;

int main()
{
    int personID = 0;
    personID += 1;
}

Here, g_NumPersons is in global scope. This is generally accepted as bad practice, because tracking the logic used in this variable against all lines of code is hard to do, and can lead to logic errors.


Sometimes, we need to share information from certain variables in other variables. Making a copy of this information, but in a variable that is a different type, is referred to as type casting.

Type Casting

To type cast a variable, you do the following expression.

int other_var = -1;
unsigned int x = (unsigned int)other_var;

Seems easy enough, right? Well, yes. Most of the time. However, typecasting variables of different types has effects on the variables that is important to understand.

Signedness Casting

int other_var = -1;
unsigned int x = (unsigned int)other_var;

In this example, we cast a negative value to an unsigned value. It's important to understand under the hood how signedness will effect the value of this variable in an unsigned fashion. For example, -1 becomes MAX_INT in the following value.

Up Casting

short other_var = -1;
int x = (unsigned int)other_var;

When you cast up a variable from one size to a larger size, the signedness comes with it. For example, here, despite shorts being 16 bits and integers being 32 bits, the value -1 will be sign extended through the larger variable.

Down Casting

int x = 0xfffffefe;
short other_var = (short)int;

When you cast a larger variable to a smaller variable, the number will be truncated because you cannot fit the entire size of the larger variable into the smaller variable.

Floats

float f = 3.14
int wasafloat = (int)f;

Floats or doubles can be cast to other variable types. It's important to understand that under the hood, assembly instructions are generated in the FPU of the processor to execute this conversion. In other casts, the data has not been significantly manipulated to enable the cast. In this case, the IEEE704 type must be manipulated to reveal the scalar value.


Resources