Skip to content

C Variables

A variable is a name given to a storage location in memory that our programs can manipulate. Each variable in C has:

  • A type, which determines the size and layout of the variable’s memory, the range of values it can hold, and the operations that can be performed on it.
  • A name (identifier) used to access that memory location.
  • A value stored at that location.

Variable names can be composed of letters (a-z, A-Z), digits (0-9), and the underscore character (_). They must begin with either a letter or an underscore. C is case-sensitive, so myVar and myvar are distinct variables.

C offers several fundamental data types:

TypeDescription
charTypically a single byte (octet). An integer type used to store character values (like 'A') or small integers. Can be signed or unsigned.
intThe processor’s natural size for integers. Size varies (e.g., 16, 32, or 64 bits). Can be short, long, long long, and signed (default) or unsigned.
floatSingle-precision floating-point value (for numbers with fractional parts).
doubleDouble-precision floating-point value (typically offers more precision and range than float).
long doubleExtended-precision floating-point value (may offer more precision than double).
_Bool (C99)Boolean type, can hold 0 (false) or 1 (true). Include <stdbool.h> to use the more convenient bool, true, and false identifiers.
voidRepresents the absence of a type. Used for functions that return nothing or accept no arguments, and for generic pointers (void*).

For precise control over integer sizes, especially for portability, use the types defined in &lt;stdint.h&gt; (C99), such as int8_t, uint32_t, int64_t, etc.

It’s crucial to understand the difference:

  • Definition: Tells the compiler to allocate storage for the variable. A variable can only be defined once in a program within a given scope.
  • Declaration: Tells the compiler about the variable’s name and type but doesn’t allocate storage. It’s an assurance that a definition exists elsewhere. A variable can be declared multiple times.
  • Most variable statements (like int count; inside a function) are definitions.

A definition specifies the data type, followed by a list of one or more variable names separated by commas. It allocates memory.

type variable_list;

Examples of definitions:

int score, level, bonus; // Defines three integer variables
char initial = 'J'; // Defines and initializes a character variable
float temperature = 98.6f; // Defines and initializes a float variable
double pi; // Defines a double-precision variable
unsigned long population; // Defines an unsigned long integer

Initialization: Variables can be assigned an initial value when defined using the = operator.

int counter = 0;
char grade = 'A', status = 'P'; // Define and initialize multiple variables

Default Initial Values:

  • Variables with static storage duration (globals, static locals) are implicitly initialized to zero (or NULL for pointers) if no initializer is provided.
  • Variables with automatic storage duration (non-static locals) have indeterminate initial values if not explicitly initialized. Using them before assigning a value leads to undefined behavior.

A declaration introduces a name and type to the compiler, typically for a variable or function defined in another file. The extern keyword is used for this purpose.

extern type variable_name;

Declarations are often placed in header files (.h) to be included in multiple source files that need to access the same global variable or function.

Example of Declaration and Definition Across Files:

Section titled “Example of Declaration and Definition Across Files:”

globals.h (Header File - Declarations)

#ifndef GLOBALS_H
#define GLOBALS_H
// Declaration of a global variable (definition is elsewhere)
extern int global_counter;
// Declaration of a function (definition is elsewhere)
extern void update_status(char status);
#endif // GLOBALS_H

globals.c (Source File - Definitions)

#include "globals.h" // Optional but good practice
#include <stdio.h> // For printf
// Definition of the global variable
int global_counter = 0;
// Definition of the function
void update_status(char status) {
printf("Status updated to: %c\n", status);
global_counter++; // Can access the global counter
}

main.c (Source File - Using Globals)

#include <stdio.h>
#include "globals.h" // Include declarations
int main(void) {
printf("Initial global counter: %d\n", global_counter);
update_status('A');
update_status('B');
printf("Final global counter: %d\n", global_counter);
return 0;
}

Compile and Link (using GCC):

gcc main.c globals.c -o myapp

Running ./myapp produces:

Initial global counter: 0
Status updated to: A
Status updated to: B
Final global counter: 2

Expressions in C can be categorized based on whether they can appear on the left-hand side of an assignment:

  • lvalue (Locator Value): An expression that refers to a memory location (object). It has an address. Variables are lvalues. An lvalue can appear on the left-hand side (variable = ...) or right-hand side (... = variable) of an assignment.
  • rvalue (Read Value): An expression that represents a data value itself, but doesn’t necessarily correspond to a specific, addressable memory location (or whose address cannot be taken). Literals (like 10, 'A') and the results of most operators (like x + y) are rvalues. An rvalue can typically only appear on the right-hand side of an assignment.

Examples:

int score = 95; // 'score' is an lvalue, '95' is an rvalue
int bonus = 10;
int total;
total = score + bonus; // 'total' is an lvalue
// 'score' and 'bonus' act as rvalues here (their values are read)
// 'score + bonus' produces an rvalue
// score + bonus = 100; // Error: 'score + bonus' is an rvalue, cannot assign to it
// 50 = total; // Error: '50' is an rvalue (a literal)

Understanding lvalues and rvalues helps clarify assignment rules and the behavior of operators like address-of (&), which requires an lvalue operand.