Skip to content

Variables



Why Do We Need Variables?

Think about a basic physical calculator. You punch in a number, multiply it, and get a result. If you need that result again later, you either write it on paper or use the calculator's memory button.

Programs process data millions of times a second. If we type 0.075 every time we want a 7.5% tax rate, the code becomes brittle: when the rate changes next year, we have to hunt down every copy.

We need a way to store information, give it a name, and reuse it. We need a variable.


What Is a Variable?

Definition

A variable is a named entity in a program that refers to a value, and that can be given a new value as the program runs.

Three things are worth keeping in mind whenever you meet one:

  1. The name you use to refer to it, such as taxRate.
  2. The value it currently refers to, such as 0.075.
  3. The type of that value, which decides what may be done with it.

How those three are represented, and how tightly they are tied together, differs from language to language.

If a data type is the kind of information, a variable is how your program refers to a particular piece of it.

Note

A box in memory is a good picture and a poor rule. A compiler may keep a variable in a CPU register, reuse one slot for several variables, or work the value out while compiling and never store it at all. Memory picks this up properly.


Declaring a Variable

Before a program can refer to a variable, the variable must be introduced according to the language's rules. This is called declaration. In a statically typed language you also state what kind of value it will hold:

Code
int score;       // "I need a box for an integer, label it 'score'"String username; // "I need a box for text, label it 'username'"

The name now exists and the program knows its type. Whether it also has a usable value depends on where it was declared: the two above are Java locals, which have none yet, while a field on an object is given 0, false or null automatically.


Initializing a Variable

Initialization gives the variable its first value.

Code
score = 0;

Usually the two are combined into one line, which is the common case:

Code
int score = 0;

Trying to read a variable before it has a valid value is handled differently across languages:

  • Java refuses to compile: a local must be definitely assigned before it is read.
  • Python raises a NameError the moment you try.
  • C and C++ allow some variables to exist without an explicit initializer, but reading an uninitialized value can lead to invalid or undefined behaviour depending on the language, type, and context.

As a good programming habit, initialize a variable before you rely on its value. The exact rules for uninitialized variables depend on the language and context.


Assigning and Updating Values

Changing a variable's value later is reassignment, and this is where = catches beginners out. It does not mean "is equal to"; it means assign the value on the right to the variable on the left.

Code
score = 50        # Put 50 into the score variablescore = 100       # Throw away the 50, put 100 in the score variable

The rule is that the right-hand side is evaluated first, and the resulting value is assigned to the variable on the left. That is why you will see this line everywhere:

Code
score = score + 10

In maths, x = x + 10 is impossible. In programming it makes sense: the right side is worked out first (score + 10), and that total is then assigned back to score.


Variables and Memory

Variables are a programming abstraction for referring to values. Where a value is actually kept - memory, a CPU register, somewhere else again - is handled by the language implementation.

We will study how variables relate to memory in the Memory chapter.


Variables and Types

Two ideas get confused here, so it is worth separating them.

In a statically typed language, the type of a variable or expression is determined and checked by the language's compile-time type system:

Code
int age = 25;age = "Hello";   // error: String is not assignable to int

In a dynamically typed language, type checking happens at runtime, and a name can be associated with values of different types over time:

Code
age = 25        # age refers to an integer objectage = "Hello"   # now it refers to a string object

Nothing is converted and no box is swapped: age is a name, and rebinding it points it elsewhere.

Note

Type inference is a third, separate idea. Java's var age = 25; and C++'s auto age = 25; let the compiler work the type out from the initial value. age is still an int, still checked at compile time, and still cannot hold a string later - inferred rather than written down, and no less static for it.


Naming Variables

The name is called an identifier, and the rules are strict: letters, digits and underscores only, no spaces, never starting with a digit (user1 is valid, 1user is not), and case-sensitive, so Score and score are different variables.

Because spaces are out, conventions fill the gap:

  • camelCase: First word lowercase, every later word capitalised (highestPlayerScore). Conventional in Java and JavaScript.
  • snake_case: All lowercase, words separated by underscores (highest_player_score). Conventional in Python.
  • PascalCase: Every word capitalised (HighestPlayerScore). Usually reserved for classes and types rather than variables.

These are conventions, not language rules: the compiler accepts any legal identifier. C++ has no single standard, and both forms are common depending on the project.

Booleans read best as a question. Prefixing with is, has or can makes the code read like a sentence: isLoggedIn, hasPermission, canEdit. Compare if (isLoggedIn) with if (login).

Meaningful names are critical. Code is read far more often than it is written, and x tells the reader nothing where daysUntilExpiration explains exactly what the data is doing.


Constants

Sometimes a program should prevent a variable or binding from being reassigned. Languages provide constants or constant bindings for this purpose: pi, a tax rate, a configuration setting.

  • Java: Uses the final keyword (final double PI = 3.14159;)
  • C++ / JavaScript: Uses the const keyword (const double PI = 3.14159;)
  • Python: Has no language-enforced constant for an ordinary variable. By convention, a name in ALL_CAPS signals that it should not be reassigned (PI = 3.14159).

Reassigning a constant is caught at different moments. Java and C++ reject it while compiling, so the program never builds. JavaScript throws a TypeError while the program is running.

Note

A constant stops the name being reassigned. It does not always freeze what the name refers to.

Code
const user = {};user.name = "Ashu";   // allowed: the object is changed, not the bindinguser = {};            // TypeError: the binding cannot be reassigned

These keywords are similar in purpose, but their exact semantics differ. In JavaScript, const prevents reassignment of the binding. In Java, final prevents reassignment of the variable. C++'s const is part of its type system and can also make an object non-modifiable through that particular access.


Scope of a Variable

Scope is the region of a program in which a name can be used. The rules belong to the language, but three levels turn up almost everywhere:

  • Local: the variable belongs to the function that declared it.
  • Block: it belongs to a smaller region inside a function, such as the body of an if or a for.
  • Module or global: it is declared outside any function, and a wider part of the program may reach it.

How those regions are marked differs. Java and C++ use braces to define many block scopes, so a variable declared inside an if cannot be referred to after that block. Python has no block scope here: a name first assigned inside an if is still visible afterwards, because Python's unit is the function. In JavaScript, let and const are block-scoped while the older var is function-scoped, which is why modern code prefers the first two.

Declare int playerHealth = 100; inside a "Start Game" function, then try to use it in an "End Game" function, and the program will not compile: the name is not in scope there.


Scope vs Lifetime

Scope describes where a variable can be accessed. Lifetime describes how long that variable exists during execution.

They are related but different, and one more point is worth knowing now: the lifetime of a variable is not necessarily the lifetime of an object it refers to. Stack and Heap takes that apart.


Variables Across Languages

FeatureJava / C++PythonJavaScript
Declarationint age = 25;age = 25let age = 25;
TypingStaticDynamicDynamic
ReassignmentChecked against the language's type rulesCan be any typeCan be any type
Constantsfinal / constALL_CAPS conventionconst

Java and C++ need a variable's type to be known while compiling, but that does not mean you always write it out: var age = 25; in Java and auto age = 25; in C++ let the compiler work it out from the value. Both are still statically typed.


Variables in DSA

Almost every algorithm you will write is a small number of variables being updated in a loop:

  • Counters and positions such as i, left and right track where you are in a structure. (Positions, not pointers in the C++ sense - the word gets used loosely for both.)
  • Accumulators such as sum, count and max are usually initialized before the loop, so their value carries from one iteration to the next. Initializing them inside resets them every pass, one of the most common beginner bugs.
  • A temporary is what makes a swap possible: temp = a; a = b; b = temp; - something sorting algorithms do thousands of times.
  • In recursion, each function call gets its own set of local variables. That is why a recursive function can have different values for the same local variable in different calls, and why deep recursion costs memory.

Common Mistakes

Watch out

  • Using a variable before initialization: Asking the computer to print score before you have assigned a number to it.
  • Confusing = with ==: = assigns a value. == checks if two values are equal. Writing if (score = 100) instead of if (score == 100) will break your code.
  • Using an invalid identifier: Trying to start a variable name with a number (1stPlace).
  • Re-declaring instead of updating: Declaring a fresh variable inside a loop when you meant to update the one outside it, then wondering why the total never grows.
  • Expecting a constant to freeze an object: final and const stop the name being reassigned, not the object being modified.

Quick Check

  1. What is the difference between declaring a variable and initializing it?
  2. What does the = operator actually do?
  3. Can a constant be reassigned after it has been initialized?
  4. If a local variable is declared inside one function, can another function access that variable directly?
  5. Why is a variable named u worse than a variable named activeUserCount?
Show answer
  1. Declaration reserves the storage and fixes the name, and in a statically typed language the type as well. Initialization puts the first value into it. int score; declares, score = 0; initializes, and int score = 0; does both.
  2. It assigns. The expression on the right is evaluated first, and the result is stored in the variable on the left. It is not a claim that the two sides are equal, which is why score = score + 10 makes sense in code and not in algebra.
  3. No. Java and C++ reject the reassignment at compile time, and JavaScript throws a TypeError at run time. Python has no enforced constants, only the ALL_CAPS convention.
  4. No. A local name exists only inside its own scope, so another function cannot refer to it. You share the value instead - by passing it as an argument, returning it, or using whatever wider scope the language provides.
  5. Because the name is the only explanation most readers get. u forces them to read the surrounding code to work out what it holds; activeUserCount says it outright, and code is read far more often than it is written.

Quick Recap

  • A variable is a name your program uses to refer to a value, and it can usually be given a new one.
  • Declaration introduces the variable; initialization gives it its first value.
  • Assignment (=) evaluates the right-hand side first, then assigns the result to the name on the left.
  • Static typing fixes the type at compile time; dynamic typing attaches it to the value. Type inference is separate again.
  • Scope is where a name can be used; lifetime is how long it exists - and neither is the same as the lifetime of a value it refers to.
  • Constants cannot be reassigned, which is not the same as the value being unchangeable.
  • Good naming carries more meaning than any comment, and booleans read best as a question: isLoggedIn, hasPermission.

Where This Leads

You can now identify what kind of value you are working with (Data Types) and give that value a name your program can use (Variables). Next comes doing something with it, which takes maths, logic and comparisons: Operators.

Data Types → Variables → Operators → Conditions → Loops → Functions → Memory

Key takeaway

A variable gives your program a name for a value, making that value easy to access and, when allowed by the language, update.