Category: C++

  • Arrays

    Arrays in C++

    In C++, an array is a collection of elements of the same data type, stored in contiguous memory locations. It allows you to store multiple values in a single variable and access them using an index. The size of the array must be specified at the time of declaration, and it cannot be changed later

    Declaring and Initializing Arrays

    Here’s how to declare and initialize arrays in C++:

    1. Single-dimensional Array: This is the simplest form of an array.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        // Declare and initialize a single-dimensional array
        int numbers[5] = {1, 2, 3, 4, 5};
    
        // Access and print array elements
        for (int i = 0; i < 5; i++) {
            cout << "Element at index " << i << ": " << numbers[i] << endl;
        }
    
        return 0;
    }

    Output:

    Element at index 0: 1
    Element at index 1: 2
    Element at index 2: 3
    Element at index 3: 4
    Element at index 4: 5

    2. Multi-dimensional Array: Arrays can have more than one dimension. A two-dimensional array is commonly used to represent matrices.

    #include <iostream>
    using namespace std;
    
    int main() {
        // Declare and initialize a two-dimensional array
        int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    
        // Access and print array elements
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 3; j++) {
                cout << "Element at [" << i << "][" << j << "]: " << matrix[i][j] << endl;
            }
        }
    
        return 0;
    }

    Output:

    Element at [0][0]: 1
    Element at [0][1]: 2
    Element at [0][2]: 3
    Element at [1][0]: 4
    Element at [1][1]: 5
    Element at [1][2]: 6
    Important Points about Arrays in C++:
    • Indexing: Array indexing starts from 0. The first element is accessed using index 0, the second with index 1, and so on.
    • Size Limitation: The size of the array must be a constant expression and cannot be modified after declaration.
    • Memory Management: The size of the array affects memory usage. For large data sets, dynamic arrays (using new keyword) or std::vector from the STL (Standard Template Library) can be used for flexibility.
    Dynamic Arrays

    If you need to create an array whose size can be determined at runtime, you can use dynamic memory allocation.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        int size;
        cout << "Enter the size of the array: ";
        cin >> size;
    
        // Dynamically allocate an array
        int* dynamicArray = new int[size];
    
        // Initialize array elements
        for (int i = 0; i < size; i++) {
            dynamicArray[i] = i * 2;  // Assigning values
        }
    
        // Print the array elements
        for (int i = 0; i < size; i++) {
            cout << "Element at index " << i << ": " << dynamicArray[i] << endl;
        }
    
        // Free the allocated memory
        delete[] dynamicArray;
    
        return 0;
    }

    Output:

    Enter the size of the array: 5
    Element at index 0: 0
    Element at index 1: 2
    Element at index 2: 4
    Element at index 3: 6
    Element at index 4: 8

    But we can have array of void pointers and function pointers. The below program works fine.

    int main()
    {
        void *arr[200];
    }

    How to print size of array parameter in C++?

    In C++, calculating the size of an array can be misleading when done within functions. Here’s an example that illustrates this issue.

    // A C++ program demonstrating the incorrect method
    // of computing the size of an array passed to a function
    #include <iostream>
    using namespace std;
    
    void checkSize(int arr[])
    {
        cout << sizeof(arr) << endl;
    }
    
    int main()
    {
        int a[10];
        cout << sizeof(a) << " ";
        checkSize(a);
        return 0;
    }

    Output:

    40 8

    Time Complexity: O(1)
    Auxiliary Space: O(n) (where n is the array size)

    In the output, the first cout statement in main() displays 40, while the second in checkSize() shows 8. The difference arises because arrays are passed as pointers to functions. Thus, both checkSize(int arr[]) and checkSize(int *arr) are equivalent. The output inside checkSize() reflects the size of a pointer, not the array.

    // A C++ program demonstrating how to use a reference
    // to find the size of an array
    #include <iostream>
    using namespace std;
    
    void checkSize(int (&arr)[10])
    {
        cout << sizeof(arr) << endl;
    }
    
    int main()
    {
        int a[10];
        cout << sizeof(a) << " ";
        checkSize(a);
        return 0;
    }

    Output:

    40 40

    Time Complexity: O(1)
    Space Complexity: O(n) (where n is the array size)

    Making a Generic Function

    Example:

    // A C++ program to demonstrate how to use templates
    // and references to find the size of an array of any type
    #include <iostream>
    using namespace std;
    
    template <typename T, size_t n>
    void checkSize(T (&arr)[n])
    {
        cout << sizeof(T) * n << endl;
    }
    
    int main()
    {
        int a[10];
        cout << sizeof(a) << " ";
        checkSize(a);
    
        float f[20];
        cout << sizeof(f) << " ";
        checkSize(f);
        return 0;
    }

    Output:

    40 40
    80 80

    Time Complexity: O(1)
    Space Complexity: O(n) (where n is the array size)

    Determining the Size of a Dynamically Allocated Array

    The next step involves printing the size of a dynamically allocated array. Here’s a hint to get you started:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    int main()
    {
        int *arr = (int*)malloc(sizeof(int) * 20);
        // Note: You need to keep track of the size since sizeof will not work here
        return 0;
    }

    In this case, since malloc returns a pointer, you cannot directly determine the size of the allocated memory using sizeof.

    What is Array Decay in C++?

    Array decay refers to the loss of both type and dimensions of an array, which typically occurs when an array is passed to a function by value or pointer. In this process, the first address of the array is sent, treating it as a pointer. As a result, the size reported is that of the pointer, not the actual size of the array in memory.

    // C++ code to demonstrate array decay
    #include <iostream>
    using namespace std;
    
    // Function demonstrating Array Decay
    // by passing array as a pointer
    void demonstrateArrayDecay(int* p)
    {
        // Displaying the size of the pointer
        cout << "Size of the array when passed by value: ";
        cout << sizeof(p) << endl;
    }
    
    int main()
    {
        int a[7] = {1, 2, 3, 4, 5, 6, 7};
    
        // Displaying the original size of the array
        cout << "Actual size of array is: ";
        cout << sizeof(a) << endl;
    
        // Passing the array to the function
        demonstrateArrayDecay(a);
    
        return 0;
    }

    Output:

    Actual size of array is: 28
    Size of the array when passed by value: 8
    How to Prevent Array Decay?

    One common approach to address array decay is to pass the size of the array as a separate parameter and to avoid using sizeof with array parameters. Another effective method is to pass the array by reference, which prevents the conversion of the array into a pointer and thus avoids decay.

    // C++ code to demonstrate prevention of array decay
    #include <iostream>
    using namespace std;
    
    // Function that prevents array decay
    // by passing the array by reference
    void preventArrayDecay(int (&p)[7])
    {
        // Displaying the size of the array
        cout << "Size of the array when passed by reference: ";
        cout << sizeof(p) << endl;
    }
    
    int main()
    {
        int a[7] = {1, 2, 3, 4, 5, 6, 7};
    
        // Displaying the original size of the array
        cout << "Actual size of array is: ";
        cout << sizeof(a) << endl;
    
        // Calling the function by reference
        preventArrayDecay(a);
    
        return 0;
    }

    Output:

    Actual size of array is: 28
    Size of the array when passed by reference: 28

    Preserving array size by passing a pointer to the array:

    Another way to maintain the size is by passing a pointer to the array, which includes an extra dimension compared to the original array.

    #include <iostream>
    using namespace std;
    
    // Function to demonstrate Array Decay with a pointer
    void pDecay(int (*p)[7]) {
        // Display the size of the pointer to the array
        cout << "Size of array when passing a pointer: ";
        cout << sizeof(p) << endl;
    }
    
    int main() {
        int a[7] = {1, 2, 3, 4, 5, 6, 7};
    
        // Display original size of the array
        cout << "Original size of array: ";
        cout << sizeof(a) << endl;
    
        // Passing a pointer to the array
        pDecay(&a);
    
        return 0;
    }

    Output:

    Original size of array: 28
    Size of array when passing a pointer: 8
  • Functions

    Functions in C++

    A function is a set of statements designed to perform a specific task and is executed only when called. Functions allow you to modularize code, reducing redundancy and improving clarity. By encapsulating common tasks within functions, we avoid repeating the same logic multiple times, making the code more manageable and easier to maintain.

    Syntax:

    void function(int size)
    {
        int array[size];
        // code to manipulate the array
    }

    Example:

    // C++ Program to demonstrate the working of a function
    #include <iostream>
    using namespace std;
    
    // Function that takes two integers as parameters
    // and returns the larger of the two
    int max(int x, int y) {
        return (x > y) ? x : y;
    }
    
    int main() {
        int a = 15, b = 25;
    
        // Calling the max function
        int result = max(a, b);
    
        cout << "The maximum value is " << result;
        return 0;
    }

    Output:

    The maximum value is 25
    Why Do We Need Functions?
    • Code Reusability: Avoid redundancy by reusing functions across the program.
    • Modularity: Code becomes more organized and easier to understand when divided into functions.
    • Abstraction: Using functions hides internal details, making complex tasks easier to use through simple function calls.
    Function Declaration

    A function declaration tells the compiler about the function’s name, parameters, and return type. Here is an example:

    // Function declarations
    int add(int, int);         // Function with two integer parameters
    float subtract(float, int); // Function with float and int parameters
    char* reverseString(char*); // Function that returns a char pointer
    Types of Functions

    1. User-defined Functions: Functions created by the user to perform specific tasks.
    2. Library Functions: Predefined functions in C++ that you can use directly, such as sqrt(), strlen(), etc

    Passing Parameters to Functions

    There are two common ways to pass parameters to functions:

    • Pass by Value: A copy of the variable is passed. Modifications inside the function do not affect the original variable.
    • Pass by Reference: The function receives the memory address of the variable, and changes made inside the function affect the original variable.
    Function Example: Pass by Value
    #include <iostream>
    using namespace std;
    
    void modify(int x) {
        x = 50;  // Changes won't affect the original variable
    }
    
    int main() {
        int num = 10;
        modify(num);
        cout << "Value of num: " << num;  // Outputs 10
        return 0;
    }

    Function Example: Pass by Reference

    #include <iostream>
    using namespace std;
    
    void modify(int &x) {
        x = 50;  // Changes will affect the original variable
    }
    
    int main() {
        int num = 10;
        modify(num);
        cout << "Value of num: " << num;  // Outputs 50
        return 0;
    }

    Function Returning a String example: 

    #include <iostream>
    #include <string>
    
    std::string greet() {
        return "Hello, C++!";
    }
    
    int main() {
        std::string message = greet();
        cout << message;
        return 0;
    }

    Output:

    Hello, C++!

    Function Returning a Pointer example:

    #include <iostream>
    using namespace std;
    
    int* createArray(int size) {
        int* arr = new int[size];  // Dynamically allocate memory
        for (int i = 0; i < size; ++i) {
            arr[i] = i * 2;
        }
        return arr;
    }
    
    int main() {
        int* arr = createArray(5);
        for (int i = 0; i < 5; ++i) {
            cout << arr[i] << " ";  // Outputs: 0 2 4 6 8
        }
        delete[] arr;  // Free allocated memory
        return 0;
    }

    Output:

    0 2 4 6 8

    Callback Function Example:

    #include <iostream>
    using namespace std;
    
    typedef void (*Callback)();  // Define a callback function type
    
    void action(Callback callback) {
        cout << "Performing action...\n";
        callback();  // Call the passed callback function
    }
    
    void myCallback() {
        cout << "Callback function executed!";
    }
    
    int main() {
        action(myCallback);
        return 0;
    }

    Output:

    Performing action...
    Callback function executed!
    Differences Between Call by Value and Call by Reference
    Call by ValueCall by Reference
    A copy of the value is passed.The reference (memory address) is passed.
    Changes do not affect the original.Changes affect the original.
    Actual and formal parameters are stored at different locations.Actual and formal parameters share the same location.

    return statement

    The return statement in C++ transfers control back to the function that invoked the current function. Once the return statement is executed, the function ends and any subsequent code in that function is ignored. For non-void functions, a return statement must return a value, while in void functions, the return statement can be omitted or used without returning any value.

    Syntax:

    return [expression];
    Functions Without a Return Value (void Functions)

    In C++, if a function is defined with a void return type, it does not return any value. The return statement is optional and can be used to exit the function early, but it should not return any value.

    Example:

    // C++ Program demonstrating a void function without a return statement
    #include <iostream>
    using namespace std;
    
    void displayMessage() {
        cout << "Hello, World!";
    }
    
    int main() {
        displayMessage();  // Function call
        return 0;
    }

    Output:

    Hello, World!
    Functions With return in a Void Function:

    In a void function, the return statement can be used simply to exit the function early.

    Example:

    // C++ Program using return in a void function
    #include <iostream>
    using namespace std;
    
    void checkValue(int x) {
        if (x < 0) {
            return;  // Exit the function early if x is negative
        }
        cout << "The value is non-negative: " << x << endl;
    }
    
    int main() {
        checkValue(-5);  // Function call
        checkValue(10);  // Function call
        return 0;
    }

    Output

    The value is non-negative: 10

    Default Arguments in C++

    In C++, a default argument is a value that is automatically provided by the compiler when a calling function does not specify a value for the argument. If a value is passed for the argument, it overrides the default value.

    Example : Default Arguments in a Function

    The following C++ example demonstrates the use of default arguments. We don’t need to write multiple functions for different numbers of arguments; one function can handle various cases by using default values for some parameters.

    // C++ Program to demonstrate Default Arguments
    #include <iostream>
    using namespace std;
    
    // Function with default arguments
    // It can be called with 2, 3, or 4 arguments.
    int sum(int x, int y, int z = 0, int w = 0) {
        return (x + y + z + w);
    }
    
    // Driver Code
    int main() {
        // Case 1: Passing two arguments
        cout << sum(10, 15) << endl;
    
        // Case 2: Passing three arguments
        cout << sum(10, 15, 25) << endl;
    
        // Case 3: Passing four arguments
        cout << sum(10, 15, 25, 30) << endl;
    
        return 0;
    }

    Output:

    25
    50
    80
    Key Points to Remember:

    1. Inlining is a suggestion, not a directive. The compiler may choose to ignore the inline request.

    2. The compiler may not inline the function if it contains:

    • Loops (for, while, or do-while)
    • Static variables
    • Recursive calls
    • A return type other than void and lacks a return statement
    • Complex constructs such as switch or goto
    Why Use Inline Functions?

    When a function is called, there’s an overhead for:

    1. Storing the return address
    2. Passing function arguments
    3. Transferring control to the function’s code
    4. Returning the result from the function

    For small and frequently called functions, this overhead might exceed the time it takes to execute the function itself. By inlining such functions, you avoid the cost of the function call and may improve performance. Inline functions are beneficial for small, simple functions where function call overhead might be significant relative to execution time.

    Advantages of Inline Functions:
    • Reduced Function Call Overhead: No need to jump to a new memory address for function execution.
    • No Stack Push/Pop Overhead: Parameters don’t need to be pushed or popped from the stack.
    • No Return Overhead: Control doesn’t need to be returned to the caller.
    • Potential for Context-Specific Optimization: The compiler can perform optimizations that wouldn’t be possible with regular function calls, as the function’s code is available at the point of use.
    • Smaller Code Size for Embedded Systems: Inlining small functions can sometimes produce more compact code in certain situations (e.g., embedded systems).

    Example:

    // Inline function to calculate the square of a number
    #include <iostream>
    using namespace std;
    
    inline int square(int x) {
        return x * x;
    }
    
    int main() {
        int num = 5;
    
        // Using the inline function
        cout << "Square of " << num << " is " << square(num) << endl;
    
        // Another usage of the inline function
        cout << "Square of 10 is " << square(10) << endl;
    
        return 0;
    }

    Output:

    Square of 5 is 25
    Square of 10 is 100

    Lambda Expressions

    C++11 introduced lambda expressions, which allow you to write inline functions for short snippets of code without giving them a name. These functions are useful for situations where you won’t reuse the code, and therefore don’t need to define a separate function.

    Syntax:

    // C++ program demonstrating lambda expressions
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <numeric> // for accumulate
    
    using namespace std;
    
    // Function to print vector
    void printVector(vector<int> v)
    {
        // Lambda expression to print vector elements
        for_each(v.begin(), v.end(), [](int i)
        {
            cout << i << " ";
        });
        cout << endl;
    }
    
    int main()
    {
        vector<int> v {4, 1, 3, 5, 2, 3, 1, 7};
    
        printVector(v);
    
        // Finding the first number greater than 4
        auto p = find_if(v.begin(), v.end(), [](int i)
        {
            return i > 4;
        });
        cout << "First number greater than 4 is : " << *p << endl;
    
        // Sorting the vector in descending order
        sort(v.begin(), v.end(), [](int a, int b) -> bool
        {
            return a > b;
        });
    
        printVector(v);
    
        // Counting numbers greater than or equal to 5
        int count_5 = count_if(v.begin(), v.end(), [](int a)
        {
            return a >= 5;
        });
        cout << "The number of elements greater than or equal to 5 is : "
             << count_5 << endl;
    
        // Removing duplicate elements
        auto unique_end = unique(v.begin(), v.end(), [](int a, int b)
        {
            return a == b;
        });
        v.resize(distance(v.begin(), unique_end));
        printVector(v);
    
        // Calculating factorial using accumulate
        int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int factorial = accumulate(arr, arr + 10, 1, [](int i, int j)
        {
            return i * j;
        });
        cout << "Factorial of 10 is : " << factorial << endl;
    
        // Storing a lambda in a variable to compute square
        auto square = [](int i)
        {
            return i * i;
        };
        cout << "Square of 5 is : " << square(5) << endl;
    
        return 0;
    }

    Output:

    4 1 3 5 2 3 1 7
    First number greater than 4 is : 5
    7 5 4 3 3 2 1 1
    The number of elements greater than or equal to 5 is : 2
    7 5 4 3 2 1
    Factorial of 10 is : 3628800
    Square of 5 is : 25
  • Control Structures in C

    Control structures (also called decision control statements) let a C program choose what to do next based on conditions, and repeat actions using loops. They are essential for building real programs that respond to user input, data, and changing situations.

    C control flow mainly includes:

    • Decision making: if, if-else, nested if, else-if ladder, switch, ternary ?:
    • Loops: for, while, do-while
    • Jump statements: break, continue, goto, return

    1) Why Do We Need Conditional Statements?

    In programming, you often need logic like:

    • If marks ≥ 40 → pass, else fail
    • If age ≥ 18 → eligible, else not
    • If choice is 1/2/3 → do different actions

    Conditional statements help you implement that decision-making cleanly.


    2) Decision Making in C

    2.1 if Statement

    Executes a block only if the condition is true.

    Syntax

    if (condition) {
        // executes if condition is true
    }
    

    Example

    #include <stdio.h>
    
    int main() {
        int x = 10;
    
        if (x > 5) {
            printf("x is greater than 5\n");
        }
    
        printf("Program continues...\n");
        return 0;
    }
    

    2.2 if-else Statement

    Provides two paths:

    • if condition is true → run if block
    • else → run else block

    Syntax

    if (condition) {
        // true block
    } else {
        // false block
    }
    

    Example (Even/Odd)

    #include <stdio.h>
    
    int main() {
        int num = 4956;
    
        if (num % 2 == 0) {
            printf("%d is Even\n", num);
        } else {
            printf("%d is Odd\n", num);
        }
    
        return 0;
    }
    

    2.3 Nested if / Nested if-else

    An if (or if-else) inside another if block for more complex decisions.

    Syntax

    if (condition1) {
        if (condition2) {
            // both true
        } else {
            // condition1 true, condition2 false
        }
    } else {
        // condition1 false
    }
    

    Example

    #include <stdio.h>
    
    int main() {
        int x = 15;
    
        if (x > 10) {
            if (x < 20) {
                printf("x is between 10 and 20\n");
            } else {
                printf("x is 20 or more\n");
            }
        } else {
            printf("x is 10 or less\n");
        }
    
        return 0;
    }
    

    2.4 if - else if - else Ladder

    Used when you have multiple conditions to test in order.
    The first true condition runs, and the rest are skipped.

    Syntax

    if (condition1) {
        // ...
    } else if (condition2) {
        // ...
    } else if (condition3) {
        // ...
    } else {
        // none matched
    }
    

    Example (Positive/Negative/Zero)

    #include <stdio.h>
    
    int main() {
        int number = 0;
    
        if (number > 0) {
            printf("The number is Positive\n");
        } else if (number < 0) {
            printf("The number is Negative\n");
        } else {
            printf("The number is Zero\n");
        }
    
        return 0;
    }
    

    Tip: Ladder is different from nested if because it checks conditions sequentially at the same level.


    2.5 switch Statement

    Best when you compare one expression against many constant values.

    Syntax

    switch (expression) {
        case value1:
            // ...
            break;
        case value2:
            // ...
            break;
        default:
            // ...
    }
    

    Example

    #include <stdio.h>
    
    int main() {
        int day = 3;
    
        switch (day) {
            case 1: printf("Sunday"); break;
            case 2: printf("Monday"); break;
            case 3: printf("Tuesday"); break;
            default: printf("Invalid day");
        }
    
        return 0;
    }
    

    Important: If you forget break, C will fall through into the next case.


    2.6 Ternary Operator ?:

    Short form of if-else when assigning/returning a value.

    Syntax

    condition ? expr_if_true : expr_if_false;
    

    Example

    #include <stdio.h>
    
    int main() {
        int x = 5;
        int result = (x > 0) ? 1 : 0;
        printf("Result: %d\n", result);
        return 0;
    }
    

    3) Looping Control Structures in C

    Loops help repeat tasks efficiently.

    3.1 for Loop

    Best when number of iterations is known.

    for (int i = 1; i <= 5; i++) {
        printf("HelloWorld\n");
    }
    

    3.2 while Loop

    Runs while condition remains true (entry-controlled loop).

    int i = 0;
    while (i < 5) {
        printf("Hello, World\n");
        i++;
    }
    

    3.3 do-while Loop

    Runs at least once because the condition is checked after the body.

    #include <stdbool.h>
    #include <stdio.h>
    
    int main() {
        bool condition = false;
    
        do {
            printf("This is the loop body.\n");
        } while (condition);
    
        return 0;
    }
    

    4) Jump Statements (Flow Control Helpers)

    • break → exits loop/switch immediately
    • continue → skips to next loop iteration
    • return → exits the function
    • goto → jumps to a labeled statement (rarely recommended)

    Example (break)

    for (int i = 1; i <= 10; i++) {
        if (i == 6) break;
        printf("%d ", i);
    }
    

    Output: 1 2 3 4 5


    Summary

    • Use if for simple decisions
    • Use if-else when there are two choices
    • Use nested if for multi-level checks
    • Use else-if ladder for multiple conditions in order
    • Use switch for clean multi-option branching
    • Use loops (for/while/do-while) for repetition
    • Use jump statements (break/continue/return) to control execution flow

  • Operators

    Operators in C++

    An operator is a symbol that acts on a value to perform specific mathematical or logical operations, forming the core of any programming language. In C++, a range of built-in operators is available to perform essential tasks and calculations.

    Example:

    c = a + b;

    In this example, the + symbol is the addition operator, while a and b are the operands. The addition operator tells the compiler to sum the values of a and b.

    Types of Operators in C

    The C language provides a wide array of operators, categorized into six types:

    1. Arithmetic Operators
    2. Relational Operators
    3. Logical Operators
    4. Bitwise Operators
    5. Assignment Operators
    6. Miscellaneous Operators

    1. Arithmetic Operators in C : Arithmetic operators allow us to perform standard mathematical operations. In C, there are 9 arithmetic operators:

    SymbolOperatorDescriptionSyntax
    +AdditionAdds two numeric values.a + b
    -SubtractionSubtracts the right operand from the left.a - b
    *MultiplicationMultiplies two numeric values.a * b
    /DivisionDivides two numeric values.a / b
    %ModulusGives the remainder of a division.a % b
    +Unary PlusSpecifies positive values.+a
    -Unary MinusReverses the sign of a value.-a
    ++IncrementIncreases the value of a variable by 1.a++
    --DecrementDecreases the value of a variable by 1.a--

    Example:

    #include <stdio.h>
    
    int main() {
        int a = 25, b = 5;
    
        printf("a + b = %d\n", a + b);
        printf("a - b = %d\n", a - b);
        printf("a * b = %d\n", a * b);
        printf("a / b = %d\n", a / b);
        printf("a %% b = %d\n", a % b);
        printf("+a = %d\n", +a);
        printf("-a = %d\n", -a);
        printf("a++ = %d\n", a++);
        printf("a-- = %d\n", a--);
    
        return 0;
    }

    Output:

    a + b = 30
    a - b = 20
    a * b = 125
    a / b = 5
    a % b = 0
    +a = 25
    -a = -25
    a++ = 25
    a-- = 26

    2. Relational Operators in C : Relational operators are used to compare two operands. These operators return a boolean value (true or false), depending on the comparison result.

    SymbolOperatorDescriptionSyntax
    <Less thanReturns true if the left operand is less than the right.a < b
    >Greater thanReturns true if the left operand is greater than the right.a > b
    <=Less than or equal toReturns true if the left operand is less than or equal to the right.a <= b
    >=Greater than or equal toReturns true if the left operand is greater than or equal to the right.a >= b
    ==Equal toReturns true if both operands are equal.a == b
    !=Not equal toReturns true if the operands are not equal.a != b

    Example:

    #include <stdio.h>
    
    int main() {
        int a = 25, b = 5;
    
        printf("a < b  : %d\n", a < b);
        printf("a > b  : %d\n", a > b);
        printf("a <= b: %d\n", a <= b);
        printf("a >= b: %d\n", a >= b);
        printf("a == b: %d\n", a == b);
        printf("a != b : %d\n", a != b);
    
        return 0;
    }

    Output:

    a < b  : 0
    a > b  : 1
    a <= b: 0
    a >= b: 1
    a == b: 0
    a != b : 1

    3. Logical Operators in C : Logical operators are used to combine multiple conditions. They evaluate to a boolean value (true or false).

    SymbolOperatorDescriptionSyntax
    &&Logical ANDReturns true if both operands are true.a && b
    ` `Logical OR
    !Logical NOTReturns true if the operand is false.!a

    Example:

    #include <stdio.h>
    
    int main() {
        int a = 25, b = 5;
    
        printf("a && b : %d\n", a && b);
        printf("a || b : %d\n", a || b);
        printf("!a: %d\n", !a);
    
        return 0;
    }

    Output:

    a && b : 1
    a || b : 1
    !a: 0

    C++ sizeof Operator

    The sizeof Operator in C++

    The sizeof operator is a unary operator used during compilation to determine the size of variables, data types, constants, classes, structures, and unions in bytes.

    Syntax:

    sizeof(data_type)

    Example 1:

    The following program shows how to use sizeof to find the size of various data types.

    #include <iostream>
    using namespace std;
    
    int main()
    {
        cout << "Bytes taken up by short is " << sizeof(short) << endl;
        cout << "Bytes taken up by long long is " << sizeof(long long) << endl;
        cout << "Bytes taken up by bool is " << sizeof(bool) << endl;
        cout << "Bytes taken up by wchar_t is " << sizeof(wchar_t) << endl;
        return 0;
    }

    Output:

    Bytes taken up by short is 2
    Bytes taken up by long long is 8
    Bytes taken up by bool is 1
    Bytes taken up by wchar_t is 4

    Example 2:

    This example demonstrates the size of variables of different data types using the sizeof operator.

    #include <iostream>
    using namespace std;
    
    int main()
    {
        double pi;
        bool flag;
        char grade;
    
        cout << "Bytes taken up by pi is " << sizeof(pi) << endl;
        cout << "Bytes taken up by flag is " << sizeof(flag) << endl;
        cout << "Bytes taken up by grade is " << sizeof(grade) << endl;
        return 0;
    }

    Output:

    Bytes taken up by pi is 8
    Bytes taken up by flag is 1
    Bytes taken up by grade is 1

    Example 3:

    This example demonstrates using sizeof to find the size of expressions.

    #include <stdio.h>
    
    int main() {
        int result;
    
        // Expression with multiple operators
        result = 10 * 5 + 8 / 2;
    
        printf("Result = %d\n", result);
    
        return 0;
    }

    Output:

    Bytes taken up by (m + n) is 4
    Bytes taken up by (m + x) is 8
    Bytes taken up by (n + x) is 8

    Output:

    Bytes taken up by (m + n) is 4
    Bytes taken up by (m + x) is 8
    Bytes taken up by (n + x) is 8

    Example 4:

    This example uses sizeof to calculate the size of an array.

    #include <iostream>
    using namespace std;
    
    int main()
    {
        double values[] = {2.3, 4.6, 5.1, 8.9, 10.0};
        int length = sizeof(values) / sizeof(values[0]);
        cout << "Length of the array is " << length << endl;
        return 0;
    }

    Output:

    Length of the array is 5

    Example 5: 

    This example shows how to use sizeof to find the size of a class.

    #include <iostream>
    using namespace std;
    
    class SampleClass
    {
        char id;
        int count;
    };
    
    int main()
    {
        SampleClass obj;
        cout << "Size of SampleClass object is: " << sizeof(obj) << " bytes" << endl;
        return 0;
    }

    Output:

    Size of SampleClass object is: 8 bytes

    Example 6: 

    This example demonstrates the size of different pointers using the sizeof operator.

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int *ptrInt = new int(5);
        float *ptrFloat = new float(7.2);
        char *ptrChar = new char('A');
    
        cout << "Size of pointer ptrInt is " << sizeof(ptrInt) << endl;
        cout << "Size of *ptrInt is " << sizeof(*ptrInt) << endl;
        cout << "Size of pointer ptrFloat is " << sizeof(ptrFloat) << endl;
        cout << "Size of *ptrFloat is " << sizeof(*ptrFloat) << endl;
        cout << "Size of pointer ptrChar is " << sizeof(ptrChar) << endl;
        cout << "Size of *ptrChar is " << sizeof(*ptrChar) << endl;
    
        return 0;
    }

    Output:

    Size of pointer ptrInt is 8
    Size of *ptrInt is 4
    Size of pointer ptrFloat is 8
    Size of *ptrFloat is 4
    Size of pointer ptrChar is 8
    Size of *ptrChar is 1

    Example 7:

    This example demonstrates nesting of the sizeof operator.

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int num = 3;
        double rate = 5.5;
    
        cout << "Nesting sizeof operator: sizeof(num * sizeof(rate)) is "
             << sizeof(num * sizeof(rate)) << endl;
        return 0;
    }

    Output:

    Nesting sizeof operator: sizeof(num * sizeof(rate)) is 8

    Example 8:

    This example shows how to determine the size of a structure using sizeof.

    #include <iostream>
    using namespace std;
    
    struct Record
    {
        int id;
        float score;
        char name[50];
    } record;
    
    int main()
    {
        cout << "Size of structure Record is " << sizeof(record) << endl;
        return 0;
    }

    Output:

    Size of structure Record is 56
  • Data Types

    Data Types in C++

    In C++, data types define the type of data that variables can hold, helping ensure that the stored values match the variable’s purpose. During variable declaration, data types restrict the kind of data that the variable can store, and the compiler allocates memory for that variable based on its declared type. Different data types require different amounts of memory, which may vary between machines due to hardware differences, even though the C++ code remains the same.

    C++ offers a wide variety of data types, allowing programmers to choose the most suitable type for their specific needs. These types are categorized as follows:

    1. Primitive Data Types: These are built-in data types available directly in C++, such as int, char, float, and bool.

    • Integer (int): Typically requires 4 bytes of memory and stores whole numbers.
    • Character (char): Uses 1 byte, stores single characters or ASCII values.
    • Boolean (bool): Holds true or false values.
    • Float (float): Stores single-precision decimal values, typically using 4 bytes.
    • Double (double): For double-precision decimal values, using around 8 bytes.
    • Void (void): Represents no value and is often used for functions that return nothing.

    2. Derived Data Types: These are derived from primitive types, including arrays, pointers, and references.

    3. User-Defined Data Types: Created by the programmer, these include classes, structures, and enumerations.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Size of char: " << sizeof(char) << " byte" << endl;
        cout << "Size of int: " << sizeof(int) << " bytes" << endl;
        cout << "Size of float: " << sizeof(float) << " bytes" << endl;
        cout << "Size of double: " << sizeof(double) << " bytes" << endl;
        return 0;
    }

    Output:

    Size of char: 1 byte
    Size of int: 4 bytes
    Size of float: 4 bytes
    Size of double: 8 bytes

    Data type sizes may vary depending on your compiler and system configuration.

    Datatype Modifiers

    Modifiers in C++ allow adjustments to the length of data a specific data type can hold. Modifiers include signedunsignedshort, and long.

    Table of Common Data Types with Modifiers:

    Data TypeSize (in bytes)Range
    short int2-32,768 to 32,767
    unsigned short int20 to 65,535
    unsigned int40 to 4,294,967,295
    long int4 or 8Depends on system architecture
    unsigned long int4 or 80 to larger positive values
    long long int8Large range
    unsigned long long8Larger positive values
    float4Decimal values, single-precision
    double8Decimal values, double-precision

    We can display the range of each data type by using constants from <limits.h>.

    Example:

    #include <iostream>
    #include <limits.h>
    using namespace std;
    
    int main() {
        cout << "Integer type range:\n";
        cout << "Minimum int: " << INT_MIN << endl;
        cout << "Maximum int: " << INT_MAX << endl;
    
        cout << "Floating type example:\n";
        cout << "Size of float: " << sizeof(float) << " bytes" << endl;
        cout << "Size of double: " << sizeof(double) << " bytes" << endl;
    
        cout << "Character type example:\n";
        cout << "Minimum char: " << CHAR_MIN << endl;
        cout << "Maximum char: " << CHAR_MAX << endl;
    
        return 0;
    }

    Output:

    Integer type range:
    Minimum int: -2147483648
    Maximum int: 2147483647
    Floating type example:
    Size of float: 4 bytes
    Size of double: 8 bytes
    Character type example:
    Minimum char: -128
    Maximum char: 127
    Advantages and Disadvantages

    Advantages:

    • Data types organize data effectively in a program.
    • They provide control over data size and range, reducing errors.
    • C++ offers a wide range of data types, which aids in precise programming.

    Disadvantages:

    • Incorrect data type usage can lead to unexpected behavior.
    • Some data types consume more memory, potentially affecting performance.
    • The complex type system in C++ can challenge beginners.

    Derived Data Types in C++

    In C++, data types are crucial for defining how data is stored, manipulated, and understood by the compiler. There are three main categories:

    • Pre-defined (Primitive) Data Types
    • User-defined Data Types
    • Derived Data Types

    Derived Data Types in C++ are created from pre-existing data types and include:

    • Function
    • Array
    • Pointers
    • References

    1. Function: A function is a reusable block of code designed to perform a specific task. It prevents code duplication by encapsulating instructions that can be invoked multiple times.

    Syntax:

    FunctionType FunctionName(parameters);

    Example:

    #include <iostream>
    using namespace std;
    
    int max(int x, int y) {
        return (x > y) ? x : y;
    }
    
    int main() {
        int a = 10, b = 20;
        cout << "Max is " << max(a, b);
        return 0;
    }

    Output:

    Max is 20

    2. Arrays: An array is a collection of elements stored in contiguous memory locations, all of which are of the same type. Arrays allow multiple data items to be represented with a single variable name.

    Syntax:

    DataType ArrayName[size_of_array];

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        int arr[5];
        arr[0] = 5;
        arr[2] = -10;
        arr[1] = 2;
        arr[3] = arr[0];
    
        cout << arr[0] << " " << arr[1] << " " << arr[2] << " " << arr[3];
        return 0;
    }

    Output:

    5 2 -10 5

    3. Pointers: Pointers hold the memory address of another variable. They are useful for dynamic memory allocation, manipulating data structures, and enabling functions to simulate call-by-reference.

    Example:

    #include <iostream>
    using namespace std;
    
    void displayPointerExample() {
        int var = 20;
        int* ptr = &var;
    
        cout << "Address stored in ptr = " << ptr << endl;
        cout << "Value of var = " << var << endl;
        cout << "Value pointed by ptr = " << *ptr << endl;
    }
    
    int main() {
        displayPointerExample();
        return 0;
    }

    Output:

    Address stored in ptr = 0x7ffc04f3f894
    Value of var = 20
    Value pointed by ptr = 20

    4. References: A reference is an alternative name for an existing variable. References are often used to avoid copying data and enable efficient parameter passing in functions.

    #include <iostream>
    using namespace std;
    
    int main() {
        int x = 10;
        int& ref = x;
    
        ref = 20;
        cout << "x = " << x << endl;
    
        x = 30;
        cout << "ref = " << ref << endl;
    
        return 0;
    }

    Output:

    x = 20
    ref = 30

    User Defined Data Types in C++

    User-defined data types are types that are created by the programmer, extending the built-in data types. These types include:

    • Class
    • Structure
    • Union
    • Enumeration (enum)
    • Typedef

    1. Class: Class in C++ serves as the blueprint for creating objects, encapsulating data and functions that operate on the data. It is the foundation of Object-Oriented Programming in C++.

    Syntax:

    class ClassName {
        // Access specifier
    public:
        // Data Members and Member Functions
    };

    Example:

    #include <iostream>
    using namespace std;
    
    class Student {
    public:
        string name;
    
        void display() {
            cout << "Student's name: " << name << endl;
        }
    };
    
    int main() {
        Student s1;
        s1.name = "Alice";
        s1.display();
        return 0;
    }

    Output:

    Student's name: Alice

    2. Structure : A Structure is a collection of variables (possibly of different types) under a single name. It is commonly used to group related data.

    Example:

    #include <iostream>
    using namespace std;
    
    struct Point {
        int x, y;
    };
    
    int main() {
        Point p1;
        p1.x = 5;
        p1.y = 10;
        cout << "Point: (" << p1.x << ", " << p1.y << ")" << endl;
        return 0;
    }

    Output:

    Point: (5, 10)

    3. Union: A Union is similar to a structure, but all members share the same memory location, meaning it can store only one of its members’ values at any given time.

    Example:

    #include <iostream>
    using namespace std;
    
    union Data {
        int integer;
        char character;
    };
    
    int main() {
        Data d;
        d.integer = 65;
        cout << "Integer: " << d.integer << endl;
        d.character = 'B';
        cout << "Character: " << d.character << endl;
        return 0;
    }

    Output:

    Integer: 65
    Character: B

    4. Enumeration (enum) : An Enumeration is a user-defined type consisting of a set of named integral constants. It helps improve code readability and maintainability by providing meaningful names to numeric values.

    Examples:

    #include <iostream>
    using namespace std;
    
    enum Week { Sun = 1, Mon, Tue, Wed, Thu, Fri, Sat };
    
    int main() {
        Week day = Tue;
        cout << "Day value: " << day << endl;
        return 0;
    }

    Output:

    Day value: 3

    5. Typedef : The typedef keyword in C++ allows you to create an alias for existing data types, making the code more readable and maintainable.

    Example:

    #include <iostream>
    using namespace std;
    
    typedef unsigned int UINT;
    
    int main() {
        UINT age = 25;
        cout << "Age: " << age << endl;
        return 0;
    }

    Output:

    Age: 25

    C++ Type Modifiers

    Modifiers in C++ provide additional context to basic data types, helping them better suit specific needs by changing their range or behavior. Modifiers are prefixed to primitive data types and include:

    • signed
    • unsigned
    • short
    • long

    These modifiers apply to the following built-in data types in C++:

    1. signed Modifier : The signed modifier allows a variable to hold positive and negative values, as well as zero.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Size of signed int: " << sizeof(signed int) << " bytes" << endl;
        cout << "Size of signed short: " << sizeof(signed short) << " bytes" << endl;
    
        return 0;
    }

    Output:

    Size of signed int: 4 bytes
    Size of signed short: 2 bytes

    2. unsigned Modifier : The unsigned modifier restricts a variable to non-negative values, allowing it to only hold positive integers and zero.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Size of unsigned int: " << sizeof(unsigned int) << " bytes" << endl;
        cout << "Size of unsigned short: " << sizeof(unsigned short) << " bytes" << endl;
    
        return 0;
    }

    Output:

    Size of unsigned int: 4 bytes
    Size of unsigned short: 2 bytes

    3. short Modifier : The short modifier reduces the storage size of an integer, usually used for small values in the range from −32,767 to +32,767.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Size of short: " << sizeof(short) << " bytes" << endl;
        return 0;
    }

    Output:

    Size of short: 2 bytes

    4. long Modifier : The long modifier increases the storage size for a data type, allowing it to store larger integer values.

    Example:

    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Size of long int: " << sizeof(long int) << " bytes" << endl;
        cout << "Size of long double: " << sizeof(long double) << " bytes" << endl;
        return 0;
    }

    Output:

    Size of long int: 8 bytes
    Size of long double: 16 bytes
  • Overview

    C++ is a versatile, general-purpose programming language that was developed to extend the C language by incorporating object-oriented principles. It is both imperative and compiled, making it suitable for system-level programming while also supporting application development.

    C++ was created by Bjarne Stroustrup at Bell Labs in 1983 as an enhancement to C, and it offers a multi-paradigm approach. This means that developers can write code in procedural, functional, generic, and object-oriented styles. One of the strengths of C++ is its ability to handle low-level operations, making it ideal for tasks such as operating systems and hardware drivers. At the same time, C++ is widely used in high-level applications, such as desktop software and games, due to its efficiency and performance.

    Some notable features of C++ include:
    • Object-Oriented Programming(OOP): C++ allows developers to create reusable classes and objects, encapsulating data and functionality.
    • Templates: C++ templates enable generic programming, allowing the development of reusable components that work with any data type.
    • Standard Template Library (STL): The STL provides a wide variety of algorithms and data structures for efficient programming.
    • Exception Handling: C++ supports exception handling, allowing developers to manage runtime errors more effectively.

    C++ continues to be a popular choice for developing both system-level software and complex applications.

    Example: “Hello, World!” in C++

    #include <iostream>
    
    int main() {
        std::cout << "Hello, World!" << std::endl;
        return 0;
    }

    Output:

    Hello, World!
    Key Characteristics of C++:
    • Object-Oriented: It supports the four pillars of OOP—encapsulation, polymorphism, inheritance, and abstraction.
    • Mid-Level Language: C++ bridges the gap between low-level operations like hardware access and high-level features like user interface development.
    • Compiled: Being a compiled language, C++ code is converted into machine code, which results in fast execution.
    • Platform Dependent: While C++ programs can run on multiple platforms (Windows, macOS, Linux), an executable built on one platform won’t necessarily run on another.
    • Manual Memory Management: C++ provides explicit control over memory allocation through pointers and dynamic memory, although this can lead to errors if not handled carefully.

    Example: Simple Class in C++

    #include <iostream>
    #include <string>
    
    class Employee {
    public:
        int emp_id;
        double salary;
    
        void display() {
            std::cout << "Employee ID: " << emp_id << ", Salary: " << salary << std::endl;
        }
    };
    
    int main() {
        Employee emp;
        emp.emp_id = 101;
        emp.salary = 50000;
        emp.display();
        return 0;
    }

    Output:

    Employee ID: 101, Salary: 50000
    Applications of C++:
    • Operating Systems: Many OS components are written in C++.
    • Browsers: Parts of Chrome and Firefox are developed in C++.
    • Games and Graphics: C++ powers major game engines and graphic applications.
    • Database Systems: Popular databases like MySQL use C++.
    • Distributed Systems: C++ is used in cloud services and distributed applications.
    Advantages of C++:
    • Performance: Due to its compiled nature, C++ offers high performance.
    • Rich Libraries: STL and other libraries simplify programming.
    • Object-Oriented: Allows for organized and reusable code.
    • Platform Independence: Though not portable in binary form, C++ source code can be compiled across various platforms.
    Disadvantages of C++:
    • Complexity: The language’s syntax and features can be hard to master, especially for beginners.
    • Error-Prone: With manual memory management, developers must be cautious of memory leaks and segmentation faults.
    Fun Facts about C++:
    • The name “C++” reflects an incremental improvement over C, with “++” being the increment operator.
    • C++ supports multiple programming paradigms, making it highly versatile for different applications.
      It was one of the earliest languages to support object-oriented programming, inspired by Simula67. 

    Features of C++

    C++ is a general-purpose programming language developed to extend the C language by incorporating object-oriented concepts. It is both imperative and compiled, offering a wide range of features. Below are some key features of C++:

    1. Object-Oriented Programming: C++ introduces Object-Oriented Programming (OOP), allowing for the creation of classes and objects. It supports essential OOP principles like encapsulation, polymorphism, inheritance, and abstraction, making it easier to design reusable and maintainable code. Key OOP concepts in C++ include:

    • Class
    • Objects
    • Encapsulation
    • Polymorphism
    • Inheritance
    • Abstraction

    2. Machine Independent: While a compiled C++ program is platform-dependent (meaning an executable created on Linux won’t run on Windows), the C++ code itself can be machine-independent. You can write the same C++ code on different platforms like Linux, Windows, or macOS, but the compiled binaries are specific to each operating system.

    3. Simple: C++ is designed to be simple and efficient, with logical structures and rich library support. One feature that simplifies development is the auto keyword, which allows the compiler to automatically deduce the data type.

    Example: Using auto keyword

    #include <iostream>
    using namespace std;
    
    int main() {
        auto num = 10;
        auto isActive = true;
        auto value = 4.56;
    
        cout << "num: " << num << ", isActive: " << isActive << ", value: " << value << endl;
        return 0;
    }

    4. High-Level Language: C++ is considered a high-level language as it allows developers to write programs that are closer to human language while still offering low-level features like memory management.

    5. Popular: C++ is widely used and remains popular due to its versatility, speed, and support for object-oriented programming. Many modern programming languages have borrowed features from C++.

    6. Case-Sensitive: C++ is a case-sensitive language. For example, main and Main are treated as two distinct identifiers.

    7. Compiler-Based: Unlike languages like Python, C++ requires a compiler to translate the code into an executable binary. This results in faster execution compared to interpreted languages.

    8. Dynamic Memory Allocation: C++ provides support for dynamic memory allocation using the new and delete operators. This allows developers to allocate and deallocate memory during runtime, giving more control over memory usage.

    Example: Dynamic Memory Allocation

    #include <iostream>
    using namespace std;
    
    int main() {
        int* ptr = new int(10);  // Dynamically allocate memory
        cout << "Value: " << *ptr << endl;
        delete ptr;  // Deallocate memory
        return 0;
    }

    9. Memory Management : C++ allows for manual memory management, offering more control compared to languages like Java and Python, which handle memory automatically. Using new and delete, you can allocate and free memory as needed.

    10. Multi-threading : C++ supports multi-threading through libraries, allowing concurrent execution of multiple threads. This is essential for developing applications that require parallel processing.

    Example: Multi-threadingj

    #include <iostream>
    #include <pthread.h>
    
    void* PrintHello(void* threadid) {
        long tid = (long)threadid;
        std::cout << "Hello from thread ID: " << tid << std::endl;
        pthread_exit(NULL);
    }
    
    int main() {
        const int NUM_THREADS = 3;
        pthread_t threads[NUM_THREADS];
        for (int i = 0; i < NUM_THREADS; ++i) {
            pthread_create(&threads[i], NULL, PrintHello, (void*)i);
        }
        pthread_exit(NULL);
        return 0;
    }

    Output:

    Hello from thread ID: 0
    Hello from thread ID: 1
    Hello from thread ID: 2

    Difference between C and C++

    C and C++ are two widely-used programming languages with a shared history, but they differ in several important aspects. Below is a fresh take on their differences:


    FeatureCC++
    OriginDeveloped by Dennis Ritchie in the early 1970s at AT&T’s Bell Labs.Created by Bjarne Stroustrup in 1979 as an extension of C, with the addition of object-oriented features.
    ParadigmC follows a procedural programming paradigm, meaning the focus is on functions and the flow of execution.C++ supports multiple paradigms including procedural, object-oriented, and generic programming, offering greater flexibility.
    Object-Oriented Programming (OOP)C does not support object-oriented programming. It relies on procedures and functions to handle data.C++ is an object-oriented language, featuring concepts like classes, objects, inheritance, polymorphism, and encapsulation.
    Data and FunctionsData and functions are separate. C programs are function-driven, meaning functions operate on data independently.In C++, data and functions are encapsulated together within objects, making programs more modular and easy to manage.
    Memory ManagementMemory allocation is handled using functions like malloc()calloc(), and memory is freed using free(). Memory management is more manual and error-prone.C++ introduces operators new and delete to manage dynamic memory allocation and deallocation, making it easier to manage memory with more control.
    Standard LibraryC’s standard library is more limited and primarily includes functions for I/O, string manipulation, and memory management.C++ includes the Standard Template Library (STL) which offers powerful features like containers (vector, list, etc.), algorithms, and iterators.
    Function OverloadingC does not support function or operator overloading, meaning functions cannot have the same name with different parameter types.C++ allows both function and operator overloading, enabling more intuitive function calls and operations on user-defined types.
    EncapsulationC does not provide direct mechanisms for encapsulation; access to data and functions cannot be restricted.C++ supports encapsulation through access modifiers (publicprivateprotected), allowing controlled access to class members.
    InheritanceC does not support inheritance, making it difficult to reuse code in an object-oriented manner.C++ allows for inheritance, where new classes can be derived from existing ones, promoting code reuse and hierarchy modeling.
    PolymorphismC doesn’t have built-in polymorphism support. Programmers can only simulate it using function pointers.C++ supports polymorphism, including function overriding and virtual functions, which allow objects to behave differently based on their types.
    CompilationC source files have .c as their extension. The compilation focuses solely on procedural code.C++ source files can have .cpp.cxx, or .cc extensions. It supports both procedural and object-oriented code, adding more complexity to the compilation process.
    NamespacesC does not have namespaces, which can lead to name conflicts in larger programs.C++ provides namespaces to group classes, functions, and variables, avoiding name collisions in large projects.
    Type SafetyC has less strict type checking compared to C++. For example, implicit conversions between different types are more common.C++ enforces stronger type checking, reducing the chances of unintended type conversions and errors.
    Exception HandlingC does not support exception handling. Errors must be handled manually using error codes and conditionals.C++ supports robust exception handling with trycatch, and throw blocks, making it easier to manage runtime errors.
    Input/OutputC uses functions like scanf() and printf() for input/output operations, which are not as type-safe or flexible.C++ uses cin and cout for input and output, offering type safety and operator overloading for cleaner syntax.
    Inline FunctionsC uses #define for macros, but these can lead to errors. Functions in C are not allowed inside structures.C++ supports inline functions that can be used within classes for performance optimization, allowing safer and more controlled macro-like behavior.
    File ExtensionsC programs typically have .c as their file extension.C++ programs use .cpp.cxx, or .cc as file extensions.
    Use CasesC is best suited for system-level programming, such as operating systems, embedded systems, and other low-level tasks where direct hardware interaction is required.C++ is used for both low-level systems programming and high-level application development, including games, GUI applications, real-time simulations, and more.

    Practical Example in C:

    #include <stdio.h>
    
    int main() {
        printf("Hello, C!\n");
        return 0;
    }
    Summary of Key Differences:
    • OOP Support: C++ is object-oriented, while C is procedural.
    • Memory Management: C++ offers a more sophisticated approach with new and delete, compared to malloc and free in C.
    • Functionality: C++ offers more advanced features like function overloading, templates, and exception handling.
    • Compilation: C++ has a more complex compilation process, supporting more paradigms compared to C’s simpler procedural focus.
  • C++ Tutorial Roadmap

    Introduction to C++

    Overview of C++

    C++ is a powerful, high-performance programming language that supports procedural, object-oriented, and generic programming. It is widely used for system software, game development, competitive programming, and performance-critical applications.

    Features of C++

    • Object-oriented programming
    • High performance and low-level memory control
    • Support for generic programming using templates
    • Rich Standard Template Library (STL)
    • Backward compatibility with C

    Difference Between C and C++

    • C is procedural; C++ supports OOP
    • C++ provides classes, objects, and templates
    • C++ offers stronger type checking and abstractions

    Data Types in C++

    Basic Data Types

    • int, float, double, char, bool, void

    Derived Data Types

    • Arrays
    • Pointers
    • References
    • Functions

    User-Defined Data Types

    • struct
    • union
    • enum
    • class

    Type Modifiers

    • short, long, signed, unsigned

    Operators in C++

    Types of Operators

    • Arithmetic operators
    • Relational operators
    • Logical operators
    • Assignment operators
    • Bitwise operators

    sizeof Operator

    • Using sizeof to determine memory size

    Control Structures

    Decision Making Statements

    • if statement
    • if…else statement
    • if-else-if ladder
    • Nested if
    • switch statement

    Relational Operators

    • Comparison operators used in conditions

    Looping Statements

    • while loop
    • do-while loop
    • for loop

    Functions in C++

    Functions Overview

    • Function declaration and definition

    return Statement

    • Returning values from functions

    Default Arguments

    • Using default parameters in functions

    Lambda Expressions

    • Anonymous functions
    • Syntax and use cases

    Arrays in C++

    Arrays Overview

    • Declaring and initializing arrays

    Array Size

    • Printing size of array parameters

    Array Decay

    • Understanding array decay behavior

    Pointers and References

    Pointers and References Overview

    • Memory addresses and aliases

    Pointers in C++

    • Pointer declaration and usage

    Types of Pointers

    • Dangling pointers
    • Void pointers
    • Null pointers
    • Wild pointers

    nullptr in C++

    • Understanding nullptr vs NULL

    References

    • Reference variables
    • Use cases

    Pointers vs References

    • Key differences and comparisons

    Strings in C++

    String Overview

    • C-style strings vs std::string

    String Functions

    • Common string manipulation functions

    Iterators

    • Traversing strings using iterators

    String Capacity

    • Capacity and size-related functions

    Dynamic Memory Management

    Dynamic Allocation

    • Using new and delete

    Comparison

    • new vs malloc()
    • delete vs free()

    Encapsulation and Abstraction

    Encapsulation

    • Data hiding using access specifiers

    Abstraction

    • Hiding implementation details

    Encapsulation vs Abstraction

    • Key differences and use cases

    Polymorphism

    Types of Polymorphism

    • Compile-time polymorphism
    • Runtime polymorphism

    Virtual Functions

    • Concept of virtual functions

    Virtual Functions in Derived Classes

    • Method overriding

    Default Arguments and Virtual Functions

    • Behavior and pitfalls

    Virtual Copy Constructor

    • Concept and use cases

    Pure Virtual Functions

    • Abstract classes

    Pure Virtual Destructor

    • Implementation details

    Static Functions and Virtuality

    • Why static functions cannot be virtual

    RTTI (Run-Time Type Information)

    • dynamic_cast, typeid

    Exception Handling

    Exception Handling Overview

    • Handling runtime errors

    Exception Handling in C++

    • try, catch, throw

    Stack Unwinding

    • Exception propagation

    Custom Exceptions

    • Creating user-defined exceptions using classes

    Templates in C++

    Introduction to Templates

    • Function templates
    • Class templates

    Templates Overview

    • Generic programming concepts

    Using Keyword

    • using vs typedef in templates

    Namespaces in C++

    Introduction to Namespaces

    • Avoiding name conflicts

    Advanced Namespace Concepts

    • Extending namespaces
    • Unnamed namespaces
    • Nested namespaces
    • Namespace aliasing

    Advanced C++ Concepts

    Standard Template Library (STL)

    • Containers
    • Iterators
    • Algorithms

    Smart Pointers

    • auto_ptr (deprecated)
    • unique_ptr
    • shared_ptr
    • weak_ptr

    this Pointer

    • Usage of this keyword

    delete this

    • Concept and risks

    Passing Functions as Parameters

    • Function pointers and functors

    Signals in C++

    • Signal handling concepts