Variables and Data Types

Variable Declaration

<type> variable_name;

Variable assignment

Using the assignment operator (=)

By default, if no values are assigned to the variable, the variable value is the old content of the address now associated to variable_name.

The assignment is from right to left:

Simple Data types

Integer

char

The values of the char type can vary from computer to computer (different machines may be based on a different character set).

The most widely used character set is ASCII (often extended to Latin-1 with characters from Western Europe and Africa).

Type
Description

signed char

8-bit integer

unsigned char

8-bit unsigned integer

int

The integer ranges are listed in the following MACROs of the library <limits.h>:

  • INT_MIN

  • INT_MAX

  • LONG_MIN

  • LONG_MAX

Number formats: If you prepend the following simbols to the integers, you can specify the numbers in a different format:

Format specifier
Format type

O

Octal

0X

Hexadecimal

Enum

  1. Declaration of the enum without its name definition:

    It defines a set of variables var1, var2, ... that can have one of the values VALUE0, VALUE1, ...

    For example:

  2. Declaration and definition of the enum

    For example:

  3. Type definition for the enum

    For example:

Integer association

  • By default, the values in the enum are associated in order to the integers 0, 1, 2, ...

    For example:

    Hence, the values are:

  • the integers associated to the enum values can be modified as follows:For example:

    Hence, the values are:

Floating point

Type
Values range
Digits

float

1.17 × 10⁻³⁸ ÷ 3.4 × 10³⁸

6 digits

double

2.2 × 10⁻³⁰⁸ ÷ 1.8 × 10³⁰⁸

15 digits

Type conversion

  • Implicit conversion

    1. logical or arithmetic expression with expressions of different types

    The int variable is converted to float in the sum, because the float has a broader range than int.

    1. assignment conversion of the variable in the RIGHT side is converted to the type of the variable in the LEFT side

    2. parameter of a function the variable passed as a parameter is converted to the one required

    3. return statement if the return value of a function is different from the required one, the value is automatically converted to the defined one

  • Explicit conversion

The expression is forcibly cast to data_type

Variable Dimension

It returns the size (number of bytes)

Type definition

#define directive

  • Definition of the new type

  • Definition of the possible values

For example:

typedef

It creates a new data type (new_type), that it is always a type variable.

Advantages:

  • Portability

  • Documentation & readability

Aggregate variables

Vector (Array)

It contains elements of the same type.

  • type: type of the elements contained in the array

  • constant_integer_expression: number of elements in the array This is usually specified by:

    • MACROs (recommended practice)

    • Magic numbers, i.e., values written directly in the declaration, large enough to ensure the array is never full

C99: Variable Length Array (VLA)

The length of the array is defined at runtime (usually, the number inside the square brackets is a variable that is later provided as input).

Indexing operator (subscripting)

For example:

Sequential continuity

The elements of the array are stored sequentially in memory.

Note: C does not check array indices during read or write operations to be FASTER (to avoid wasting clock cycles).

If you write to an array using an invalid index, you might overwrite other data in memory.

Array size

  • sizeof(a) – size in bytes of the array a

  • sizeof(a[0]) – size in bytes of the first element (i.e., the size of the element type)

Initialization

  • Explicit initialization of all elements

  • Explicit initialization of the first 3 elements and implicit initialization of the remaining elements to 0

  • Automatic assignment of the array length (# of initialized elements)

C99:

Designators allow you to initialize specific elements or fields of arrays and structs by name or index, improving clarity and flexibility.

Management of Partially Filled Arrays

Arrays are usually created with larger sizes because continuous allocations would require more intervention from the operating system.

  • Resizing due to the insertion of a new element

    If the space occupied by the array is full, a new memory area must be allocated using realloc():

    • If there is contiguous space after the array, the pointer to the same memory area is returned.

    • Otherwise, a copy of the array is made to a new memory area, and only then is the new element added.

    Usually, very large arrays are defined to minimize the number of reallocations, and therefore reduce requests to the operating system.

  • Removing an element from the array without wasting memory

Structures

  • The components are called fields (members in C terminology)

  • The components can be simple types or other data structures

  • The components are defined by names, and you access them via these names (not by position as with arrays)

Declaration of a structure

You can declare it in a .h file, but I need to use macros to avoid multiple declarations, because a struct can only be declared once.

First method

In memory, the structure members are allocated contiguously in the same order they are declared.

Depending on the architecture, there may be gaps between fields to ensure memory alignment.

Padding If a field occupies less than the number of bits in which the architecture organizes memory (e.g., 32-bit or 64-bit), and the next field doesn’t fit in the remaining space, the compiler inserts uninitialized gaps between fields for alignment purposes.

  • These padding areas are sometimes called "dirty" memory from previous usage.

  • Padding bytes are not addressable — you can't access or use them directly.

For example:

Second method

Declaration of a new data type (new_type_name):

Declaration of a struct variable

First method:

Second method:

Access to the structure fields

Example:

Initialization of the structure

First method

Each field that is not explicitly initialized is zeroed out bit by bit by the compiler.

  1. List of fields separated by commas (traditional syntax)

  1. Field declarations using colons (Not Standard - GCC syntax before standardization)

  1. Assignment using field names - designated initializers (C99 standard syntax, also supported by GCC)

Examples:

  1. Traditional syntax

  2. Not standard

  3. C99 syntax

Second method

Example:

Assignment of the variable

A deep copy of the fields of variable_name2 is made into the fields of variable_name1 (if both are struct variables).

Comparison between structure variables

You cannot directly compare two structure variables in C (e.g., using the == operator). If there is padding within the structure, the two variables will never be equal, even if the fields are the same. This is because the padding bytes are not initialized and can affect the overall memory representation of the struct.

Example:

  • t1 == t2 ➡️ NO (due to padding)

  • t1.s == t2.s && t1.i == t2.i ➡️ YES

Pointers to structures

Declaration of the pointer:

Access to the structure fields:

Bit fields

A group of bits organized into fields.

Useful for making better use of hardware on systems with limited memory

You can define data types with sizes smaller than the smallest standard data type (usually char), by using bit fields.

Bit field declaration

Each field specifies the number of bits (bit_size) that make up the field

A field can also be:

  • Anonymous (without field_name and :) used for padding of number_bit bits (cannot be used to store values)

  • Anonymous with zero size (without field_name and :, but with size 0) forces the alignment of the following field to the next memory boundary (padding)

Example:

Union

Aggregate data type that can contain multiple fields as alternatives.

Declaration

  • In memory, space is allocated for the largest field

  • It is a kind of “variant record” where the fields overlap in memory, so only one is valid at a given time

First method

Example:

Second method

Example:

Declaration of a struct variable

First method

Second method

Access to the union fields

You can access a union member only if the last assignment to the union was made through that member. (C provides no way to determine which member of a union was last assigned)

Last updated