Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is void* necessary apart from memory allocation related stuff

Is void* necessary apart from memory allocation related stuff in C++? Can you give me an example?

like image 620
RoundPi Avatar asked Sep 04 '11 11:09

RoundPi


People also ask

Does void * allocate memory?

void *malloc(size_t size); The free() function takes the pointer returned by malloc() and de-allocates the memory. No indication of success or failure is returned.

What is a void pointer?

The void pointer in C is a pointer that is not associated with any data types. It points to some data location in the storage. This means that it points to the address of variables. It is also called the general purpose pointer. In C, malloc() and calloc() functions return void * or generic pointers.

What does void mean in C?

In computer programming, when void is used as a function return type, it indicates that the function does not return a value. When void appears in a pointer declaration, it specifies that the pointer is universal. When used in a function's parameter list, void indicates that the function takes no parameters.

What is the memory size of void?

If the system is 32-bit, size of void pointer is 4 bytes. If the system is 64-bit, size of void pointer is 8 bytes.


1 Answers

Logging memory addresses

If you want to output a pointer using iostreams (e.g. for logging) then going via void* is the only way of ensuring operator<< hasn't been overloaded in some crazy way.

#include <iostream>

struct foo {
};

std::ostream& operator<<(std::ostream& out, foo*) {
  return out<<"it's a trap!";
}

int main() {
  foo bar;
  foo *ptr = &bar;

  std::cout << ptr << std::endl;
  std::cout << static_cast<void*>(ptr) << std::endl;
}

Testing iostream status

iostreams overload operator void* as a status check so that syntax like if (stream) or while (stream) is a short hand way of testing the stream status.


Template meta programming

You might want to use void* with template metaprogramming sometimes as a reduced catch all, e.g. with SFINAE tricks, but more often than not there's a nicer way around it using a partial specialisation of one form or another.


Accessing most derived pointer

As Alf pointed out in the comments dynamic_cast<void*> is also useful for getting at the most derived type in a heirarchy, e.g.:

#include <iostream>

struct other {
  virtual void func() = 0;
  int c;
};

struct foo {
  virtual void func() { std::cout << "foo" << std::endl; }
  int a;
};

struct bar : foo, other {
  virtual void func() { std::cout << "bar" << std::endl; }
  int b;
};

namespace {
  void f(foo *ptr) {
    ptr->func();
    std::cout << ptr << std::endl;
    std::cout << dynamic_cast<void*>(ptr) << std::endl;
  }

  void g(other *ptr) {
    ptr->func();
    std::cout << ptr << std::endl;
    std::cout << dynamic_cast<void*>(ptr) << std::endl;
  }
}

int main() {
  foo a;
  bar b;
  f(&a);
  f(&b);
  g(&b);
}

Gives:

foo
0xbfb815f8
0xbfb815f8
bar
0xbfb815e4
0xbfb815e4
bar
0xbfb815ec
0xbfb815e4

On my system.


Exceptions

§ 15.3.1 states:

The exception-declaration shall not denote a pointer or reference to an incomplete type, other than void*, const void*, volatile void*, or const volatile void*.

So it seems to be the only legal way of catching a pointer to an incomplete type is via void*. (Although I think there's possibly bigger issues if you actually needed to use that)


Legacy C uses

There are a lot of "legacy" C uses for void* for storing pointers to data without knowing what it is, but in new C++ code there is almost always a better way of expressing the same functionality.

like image 121
Flexo Avatar answered Oct 27 '22 08:10

Flexo