Pointers/Memory Allocation   «Prev  Next»
Lesson 7 Generic pointer type
Objective Generic pointer type as a formal parameter

void* as Formal Parameter in C++

In C++, a "generic pointer type" refers to a pointer that can point to any data type. The term typically applies to the `void*` type, which serves as a general-purpose pointer. A `void*` pointer does not have a specific data type associated with it, making it "generic."
Key Concepts of a Generic Pointer (`void*`):
  1. No Type Information:
    • A void* pointer is not associated with any specific data type. For example:
                void* ptr;
              
      Here, ptr is a generic pointer that can store the address of any type of data.
  2. Used as a Formal Parameter:
    • When used as a parameter in a function, a void* allows the function to accept pointers to any data type. This is useful when the function needs to handle multiple data types generically.
                void printValue(void* data, char type) {
                  if (type == 'i') { // Integer
                    std::cout << *static_cast<int*>(data) << std::endl;
                  } else if (type == 'f') { // Float
                    std::cout << *static_cast<float*>(data) << std::endl;
                  }
                }
              
  3. Type Casting is Required:
    • Since a void* does not carry type information, it must be explicitly cast to the appropriate type before dereferencing.
                int x = 42;
                void* ptr = &x;
                std::cout << *static_cast<int*>(ptr) << std::endl; // Type cast required
              
  4. No Pointer Arithmetic:
    • Pointer arithmetic cannot be performed directly on a void* because the compiler does not know the size of the underlying data type. If arithmetic is needed, the pointer must first be cast to the appropriate type.
  5. Use Cases:
    • void* is commonly used in low-level programming where flexibility is needed, such as:
      • Memory management: Functions like malloc and calloc in C return a void* pointer.
                      int* arr = static_cast<int*>(malloc(5 * sizeof(int)));
                    
      • Generic data structures: Data structures like linked lists or hash tables can use void* to store elements of different types.
  6. Type Safety Concerns:
    • Using void* sacrifices type safety. The programmer must ensure that the correct type is used when casting. Incorrect type casting can lead to undefined behavior.

Example: `void*` as a Generic Pointer Parameter
Here is a simple example demonstrating the use of a `void*` as a formal parameter:
#include 

void display(void* data, char type) {
    if (type == 'i') {
        std::cout << *static_cast<int*>(data) << std::endl;
    } else if (type == 'd') {
        std::cout << *static_cast<double*>(data) << std::endl;
    } else if (type == 'c') {
        std::cout << *static_cast<char*>(data) << std::endl;
    }
}

int main() {
    int num = 10;
    double pi = 3.14;
    char letter = 'A';

    display(&num, 'i');     // Output: 10
    display(&pi, 'd');      // Output: 3.14
    display(&letter, 'c');  // Output: A

    return 0;
}

Benefits and Drawbacks:
  • Benefits:
    • Flexibility: A single function or data structure can handle multiple data types.
    • Memory Efficiency: Avoids the need for duplicating code for different data types.
  • Drawbacks:
    • Lack of Type Safety: Relies on the programmer to ensure the correct type is used.
    • Complexity: Requires explicit type casting, which can lead to errors.
In modern C++, templates and polymorphism are preferred for generic programming as they provide better type safety and flexibility compared to `void*`.

C++ How to Program

Write a function that casts the generic pointer type void* to a standard working type

A key use for the generic pointer type is as a formal parameter. For example, the library function memcpy is declared in cstring as:
void* memcpy(void* s1, void* s2, size_t n);

On older C++ systems and on C systems, memcpy is found in string.h. The function memcpy copies n characters from the variable based at s2 into the variable based at s1. It works with any two pointer types as actual arguments. The type size_t is defined in stddef.h, and is often a synonym for unsigned int.
#include <cstring>
void *memcpy(void *to, const void *from, size_t count);

The memmove( ) function copies count characters from the array pointed to by from into the array pointed to by to. If the arrays overlap, the copy will take place correctly, placing the correct contents into the "to" destination, but leaving the "from" source modified. The memmove( ) function returns a pointer to to. A related function is memcpy( ).

Wide-Character Array Functions

The standard character array-manipulation functions, such as memcpy( ), also have wide-character equivalents. These functions use the header <cwchar>.
Text showcasing a table of functions for handling wide-character arrays (`wchar_t`) in C++ and their equivalent `char`-based functions.
Below is the transcribed information:
Table Analysis:
  1. Wide-Character Functions and Their char Equivalents
    • wchar_t *wmemchr(const wchar_t *str, wchar_t ch, size_t num)
      Equivalent: memchr()
    • int wmemcmp(const wchar_t *str1, const wchar_t *str2, size_t num)
      Equivalent: memcmp()
    • wchar_t *wmemcpy(wchar_t *str1, const wchar_t *str2, size_t num)
      Equivalent: memcpy()
    • wchar_t *wmemmove(wchar_t *str1, const wchar_t *str2, size_t num)
      Equivalent: memmove()
    • wchar_t *wmemset(wchar_t *str, wchar_t ch, size_t num)
      Equivalent: memset()

Example C++ Code:
Here’s an example C++ code snippet demonstrating the use of `wmemcpy`:
#include <cwchar>
#include <iostream>

int main() {
    wchar_t source[] = L"Hello, Wide World!";
    wchar_t destination[20];

    // Copying wide characters
    wmemcpy(destination, source, wcslen(source) + 1);

    std::wcout << L"Source: " << source << std::endl;
    std::wcout << L"Destination: " << destination << std::endl;

    return 0;
}

This demonstrates the usage of `wmemcpy()` to copy wide-character strings, a direct equivalent to `memcpy()` for `char`.


Generic Poitner Type - Exercise

Click the Exercise link below to write and test a function that casts the generic pointer type to a standard working type.
Generic Pointer Type - Exercise

SEMrush Software