Dr. Roger Ianjamasimanana

A comprehensive guide to data types in C

By Dr. Roger Ianjamasimanana

Data types are important in C programming as they define the nature and size of data that can be processed. This lesson introduces the various C data types available. In C, data types are categorized into primary, derived, and user-defined types. They also have their modifiers and qualifiers.

1. Primary data types in C

C data types summary table
Data types Description Memory (bytes) Range Format specifier
void Represents the absence of type. Used in functions to indicate no return value or no parameters. N/A N/A N/A
char Stores single characters such as letters, digits, or symbols. 1 -128 to 127 (signed) or 0 to 255 (unsigned) %c
int Represents integer values (whole numbers without decimal points). 4 -2,147,483,648 to 2,147,483,647 (signed) or 0 to 4,294,967,295 (unsigned) %d or %i
float Stores single-precision floating-point numbers (decimal values). 4 Approximately 1.2E-38 to 3.4E+38 %f
double Stores double-precision floating-point numbers, offering greater precision than float. 8 Approximately 2.3E-308 to 1.7E+308 %lf

Primary data types, also known as fundamental data types, are the basic building blocks in C. They represent simple values and are predefined in the language. There are five primary data types in C: void, char, int, float, and double.

1.1 Void

The void type represents the absence of type. It’s primarily used in function declarations to indicate that a function does not return a value or does not accept any parameters.


// Example of void type in function declaration
void displayMessage() {
    printf("Hello, World!\n");
}
    

1.2 Integer types (int)

Integer types are used to store whole numbers without decimal points. They vary in size and range based on their specific type.

  • int: Typically 4 bytes, used for general-purpose integers.
  • short: Usually 2 bytes, for smaller integer values.
  • long: At least 4 bytes, often 8 bytes on modern systems, for larger integers.
  • long long: At least 8 bytes, used for very large integers.

// Example of integer types
int a = 10;
short b = 20;
long c = 300000;
long long d = 4000000000;
    

1.3 Floating-point types

Floating-point types are used to store numbers that require fractional precision. They are essential for calculations involving decimals.

  • float: Single-precision, typically 4 bytes.
  • double: Double-precision, usually 8 bytes.
  • long double: Extended precision, size varies by system.

// Example of floating-point types
float e = 3.14f;
double f = 3.141592653589793;
long double g = 3.141592653589793238462643383279502884L;
    

1.4 Character types

Character types are designed to store individual characters, such as letters and symbols.

  • char: typically 1 byte, used for storing single characters.

// Example of character type
char h = 'A';
    

2. Derived data types in C

Derived data types are constructed from primary data types. They include arrays and pointers.

2.1. Arrays

Arrays are collections of elements of the same type, stored in contiguous memory locations. They allow storing multiple values under a single variable name.


    // Example of an array
    int numbers[5] = {1, 2, 3, 4, 5};
    

2.2. Pointers

Pointers store the memory addresses of other variables. They are powerful tools for dynamic memory management and efficient data manipulation.


    // Example of pointers
    int x = 10;
    int *ptr = &x;
    

3. User-defined data types

C allows programmers to create custom data types using structures, unions, and enumerations to model real-world entities more effectively.

3.1. Structures

Structures allow grouping variables of different types under a single name, facilitating the creation of complex data models.


    // Example of a structure
    struct Person {
        char name[50];
        int age;
        float height;
    };
    
    struct Person person1 = {"Alice", 30, 5.5f};
    
To learn more, read the lesson on how to use structures in C.

3.2. Unions

Unions are similar to structures but allow storing different data types in the same memory location, saving memory when variables are mutually exclusive.


    // Example of a union
    union Data {
        int integer;
        float decimal;
        char character;
    };
    
    union Data data;
    data.integer = 10;
    

3.3. Enumerations

Enumerations (enums) define a type consisting of a set of named integer constants to enhance code readability and maintainability.


    // Example of an enumeration
    enum day {
        SUNDAY,
        MONDAY,
        TUESDAY,
        WEDNESDAY,
        THURSDAY,
        FRIDAY,
        SATURDAY
    };
    
    enum day today = MONDAY;
    

3.4. Typedef

Typedef is used to create an alias for an existing data type. This can simplify complex type declarations, enhance code readability, and make maintenance easier. By using typedef, programmers can define more intuitive and meaningful names for data types, especially for complex structures or pointers.


// Example of typedef with a structure
typedef struct {
    char title[100];
    int pages;
    float price;
} Book;

Book book1 = {"C Programming", 350, 29.99f};

// Example of typedef with a pointer
typedef int* IntPtr;

IntPtr ptr;
int a = 10;
ptr = &a;

4. Type modifiers

Type modifiers alter the properties of primary and derived data types, allowing for variations in size and behavior.

  • signed: Specifies that a variable can hold both positive and negative values.
  • unsigned: Specifies that a variable can only hold non-negative values.
  • long: Extends the size of the data type.
  • short: Reduces the size of the data type.

// Example of type modifiers
unsigned int u = 100;
long long int ll = 1000000;
short int s = 10;
    

5. Type qualifiers

Type qualifiers provide additional information about how a variable can be used, enhancing data protection and optimization.

  • const: Indicates that a variable's value cannot be modified after initialization.
  • volatile: Informs the compiler that a variable's value may change unexpectedly, preventing certain optimizations.
  • restrict: Provides a hint to the compiler that a pointer is the only reference to the object it points to, allowing for optimization.

// Example of type qualifiers
const int ci = 50;
volatile float vf = 3.14f;
int * restrict ptr;
    

6. C data types best practices

Adhering to best practices ensures efficient and error-free use of data types in C programming.

✍️
Choose the right data type

Select data types that best represent the data you intend to store, considering memory usage and range.

✍️
Use type modifiers wisely

Apply type modifiers to optimize memory without sacrificing the integrity of data.

✍️
Leverage enumerations

Use enums to make code more readable and to manage sets of related constants effectively.

✍️
Protect data with qualifiers

Utilize type qualifiers like `const` to prevent unintended modifications, enhancing code safety.

✍️
Consistent naming conventions

Adopt clear and consistent naming conventions for variables and types to improve code clarity.


// Example of best practices
const float PI = 3.14159f;

enum status {
    SUCCESS,
    FAILURE,
    PENDING
};

struct rectangle {
    float length;
    float width;
};

void calculate_area(const struct rectangle *rect) {
    float area = rect->length * rect->width;
    printf("Area: %.2f\n", area);
}
    

7. Summary

C offers a robust set of data types that cater to a wide range of programming needs. From primary types like integers and floats to derived and user-defined types such as arrays, pointers, structures, and enums, understanding these types is crucial for effective C programming. By leveraging type modifiers and qualifiers, programmers can optimize memory usage and enhance data integrity. Adhering to best practices ensures that code remains efficient, readable, and maintainable.

feature-top
Readers’ comment
feature-top
Log in to add a comment
🔐 Access