6.13 — Void pointers

The void pointer, also known as the generic pointer, is a special type of pointer that can be pointed at objects of any data type! A void pointer is declared like a normal pointer, using the void keyword as the pointer’s type:

A void pointer can point to objects of any data type:

However, because the void pointer does not know what type of object it is pointing to, it cannot be dereferenced directly! Rather, the void pointer must first be explicitly cast to another pointer type before it is dereferenced.

This prints:


The next obvious questions is: If a void pointer doesn’t know what it’s pointing to, how do we know what to cast it to? Ultimately, that is up to you to keep track of.

Here’s an example of a void pointer in use:

This program prints:


Void pointer miscellany

Void pointers can be set to a null value:

Although some compilers allow deleting a void pointer that points to dynamically allocated memory, doing so should be avoided, as it can result in undefined behavior.

It is not possible to do pointer arithmetic on a void pointer. This is because pointer arithmetic requires the pointer to know what size object it is pointing to, so it can increment or decrement the pointer appropriately.

Note that there is no such thing as a void reference. This is because a void reference would be of type void &, and would not know what type of value it referenced.


In general, it is a good idea to avoid using void pointers unless absolutely necessary, as they effectively allow you to avoid type checking. This allows you to inadvertently do things that make no sense, and the compiler won’t complain about it. For example, the following would be valid:

But who knows what the result would actually be!

Although the above function seems like a neat way to make a single function handle multiple data types, C++ actually offers a much better way to do the same thing (via function overloading) that retains type checking to help prevent misuse. Many other places where void pointers would once be used to handle multiple data types are now better done using templates, which also offer strong type checking.

However, very occasionally, you may still find a reasonable use for the void pointer. Just make sure there isn’t a better (safer) way to do the same thing using other language mechanisms first!


1) What’s the difference between a void pointer and a null pointer?

Quiz answers

1) Show Solution

6.14 -- Pointers to pointers and dynamic multidimensional arrays
6.12a -- For-each loops

83 comments to 6.13 — Void pointers

  • alfonso

    "It is not possible to do pointer arithmetic on a void pointer. This is because pointer arithmetic requires the pointer to know what size object it is pointing to, so it can increment or decrement the pointer appropriately."

    It is pretty much a similar situation with dereferencing a void pointer. You can't do it directly. But you can do it somehow.

  • alfonso

    I understand the purpose of the example code here. But in 'real life' isn't better to have three explicit functions like printInt (), printFloat () and printCstring ()? The function printValue () must iterate at every call just to find the functionality for the case that we  already know at the call moment: "I have an int and I want to print an int." So why to search for a printInt () functionality through a list of functionalities?

    • You wouldn't write code like this in practice at all, as there are safer alternatives (eg. `std::variant`), but it's not easy to come up with a short example that requires the use of `void*`.
      You're right, it'd be better to call the correct function right away if the type is known. You'll see code like this in cases where the type is unknown at compile-time. This happens when you load the values and a type id or type name from a database for example. You'll have a value and only an id of the type, but you can't know which type it is at compile-time.

  • hassan magaji

    hi everyone,
    i understood the concept of void pointers quiet well but it seems to me like they're less useful, if you have to cast them everytime to a known data type why didnt you declared it to be of that data type in the first place.
    I wish to know more about their significance if i missed one.

    nice tutorials by the way.

    • Alex

      They're useful mainly when you want a generic way to point at something but will disambiguate what that is via some other mechanism. They were used more in the C world, as a way to do a primitive form of polymorphism. C++ has better mechanisms for such things (like templates), so they're not used much in C++.

  • Your article clears my confusion on void pointer, it really helps me. Thank you so much to share this useful information.

  • Louis Cloete

    I have a slightly unrelated question. I have been wondering how to write my own function to truncate a floating point number. I used type float for the parameter, since I didn't want it to be able to be too large to fit into an int. Here is my code:

    I used reinterpret casts, but upon reviewing the section on void pointers, I realised I could've used void pointers as well:

    What is considered best programming style?

    PS I may have made a mistake in the void pointer version as I changed it here in the comment and didn't compile and test.

    • Hi Louis!

      First off, good job! Your code shows a firm understanding of casts, pointers, and bitwise operations.

      > I may have made a mistake in the void pointer version
      You used the "name" variables in places where the "namePtr" variables should've been used.

      > What is considered best programming style?
      Both, void* and @reinterpret_cast allow type-unsafe conversions. In that aspect, they're the same. Since you only need to new pointer to immediately read from it, you should use @reinterpret_cast. If you were to store the pointer, you should use void* (Or @std::uintptr_t, if you want it as a number).

      Line 58 in the @reinterpret_cast version: Use the conditional operator only if you need the operations result. Otherwise, an if-statement is easier to read.

      Bear in mind that the internal representation of floating pointer numbers is not standardized in C++. You can use @std::numeric_limits::is_iec559 to check if a number fulfills the requirements of the IEEE 754 standard.

      • Louis Cloete

        Hi nascardriver! Thanks for the compliment. I have a few questions.

        1. What is @std::uintptr_t? Is it a type that can be assigned from any type pointer, but interprets the number as an unsigned int when you dereference it? Can you do this with it: [EDIT]: You can't, but I can't figure out how you would use it. What is the use for it then? Does it store the address of a variable as an int? So I can't really use it in my trunc() function?

        I couldn't get a satisfactory answer on

        PS I don't know why, but Code::Blocks doesn't autocomplete std::uintptr_t for you, but it does autocomplete uintptr_t. Similar story for all fixed width ints: it doesn't autocomplete the std:: version. Why is that? And why does the identifier without the std:: prefix compile at all? Why does it highlight the fixed width int types and uintptr_t like keywords, but not my own typedefs?

        2. About the conditional operator: do you mean this instead?

        • > What is @std::uintptr_t?
          Update: Don't use @std::uintptr_t, it's an optional type (ie. compilers don't have to support it). Use @std::uint_fast32_t or @std::uint_fast64_t instead (Or their "least" counterparts).
          It's an unsigned integer type guaranteed to be able to store any valid address. This is useful if you want to do arithmetic on the address instead of on a pointer.
          Since you're not storing addresses in @truc, you don't need it. It's an alternative to a void*.

          > Code::Blocks
          I'm using (std::)int_fast32_t as a representative for all fixed width integer types.
          @int_fast32_t is defined in @<stdint.h>
          @std::int_fast32_t is defined int @<cstdint>
          Whenever there's a <c*> and a <*.h> header, the <*.h> header is the C version, the <c*> header is the C++ version. C++ uses namespaces (In particular @std). C doesn't have namespaces, so it defines everything globally.
          The C++ standard demands the C headers to be available in C++ (for backward compatibility).
          I'm guessing a header you included (<iostream> tends to include a lot), included <stdint.h>. This allows you to use int_fast32_t, but not @std::int_fast32_t.
          If you can use @std::int_fast32_t but Code::Blocks doesn't suggest it, there's something wrong with Code::Blocks.
          I'm experiencing the same syntax highlighting behavior in Visual Studio Code. My only guess is that this is done to differentiate between system- and user types.

          > About the conditional operator: do you mean this instead?

  • Sivasankar

    You said that deleting a void pointer should be avoided. Do you mean, it(void pointer) should be converted to particular pointer type before deleting?

  • Blue

    Auto *ptr and Void *ptr are same?

  • Baschti

    Why should you not dynamically allocated memory with a void pointer?

    • Alex

      1) There's rarely a need to actually do so (unless maybe you're doing your own memory management)
      2) Deleting memory pointed to by a void pointer can cause issues (namely, destructors won't be called)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]