Concepts / Casting Between Pointer Types

Casting Between Pointer Types

In C, a void* may be assigned to a pointer of any type without a cast; in C++ this implicit conversion is not allowed.

  • Programming

A Porting Trap

A pointer assignment can look ordinary in C and still fail when the same code is compiled as C++. The key difference is how the two languages treat a conversion from void* to a pointer to a specific type.

What do you think happens?

Suppose ch is a character variable and raw points to ch through a void*. In C++, will this assignment be accepted without a cast?

  • Yes, because void* can be assigned to any pointer type in both languages.

  • No, because C++ does not allow this implicit conversion.

Reveal answer
Answer:

No. C++ does not allow assigning raw, a void*, to an int* without an explicit conversion.

C permits this assignment without a cast; C++ does not. The fact that the assignment is accepted in C does not make the converted pointer safe to use for accessing the object.

void* to int*Accepted without a castvoid* to int*Not accepted without a cast
Is the same void* to typed-pointer assignment accepted without a cast?

When a Pointer Type Misleads

A void* can point to an object of any type, but the void* itself does not say what type of object is at that address. Converting it to another pointer type makes the program treat that memory as though it were an object of the new type. If the new type is larger than the object actually stored there, writing through the converted pointer can reach neighboring bytes that belong to something else.

cpp
Notes on the code
  • The assignment from void* to int* is accepted in C but not in C++ without a cast.
  • The write illustrates the danger of treating the character object's storage as an int object.
raw void*Points to chchar object chint* pTreats the address as anintNeighboring bytespoints tostarts its write herewrite may reach
What can happen when a pointer to a larger type is used to write at the start of a smaller object?

Reviewing C Code in C++

When C code is moved into a C++ project, look for assignments that implicitly convert void* to another pointer type. Make each conversion explicit so its intended target type is visible for review. The source also notes that malloc() returns void*: in C++ its result must be cast to the right pointer type. For code that is C++ only, the guidance is to avoid malloc().

cpp
Notes on the code
  • The cast makes the intended pointer type explicit for a malloc() result.

Testing a dynamic_cast Result

A pointer-form dynamic_cast attempts to produce a pointer to the requested type. For example, requesting a Smiley* from ps checks whether the pointed-to object is a Smiley or belongs to a class derived from Smiley. If it is neither, the result is nullptr. Treat the result as something to test before using it as a pointer to the requested type.

SmileySmiley objectObject of a classderived from Smileymatchesderived type matches
Which object types meet a dynamic_cast request for Smiley*?
dynamic_cast<Smiley*>(ps)Test resultIs it nullptr?Use matching pointerHandle nullptrreturns pointer or nullptrnot nullptrnullptr
How does the program proceed from a dynamic_cast attempt to a checked pointer?
cpp
Notes on the code
  • The cast result is stored in p.
  • The condition checks that the result is not nullptr before the matching case uses p.
ifTests the resultSmiley* p =Stores the resultdynamic_castAttempts the conversion<Smiley*>Requested pointer type(ps)Pointer being checked
How do the requested type, operand, cast result, and condition fit together?

Practice the Decision

MEDIUM

For each case, predict the result before reading the hints: (1) In C++, raw is a void* and p is an int*. Is p = raw accepted without a cast? (2) A pointer-form dynamic_cast requests Smiley*, and the pointed-to object is of a class derived from Smiley. What does the cast produce? (3) The cast result is nullptr. Should the program use it as a pointer to a matching Smiley object?

Hints
  • C++ does not allow the implicit void* to typed-pointer conversion.
  • A pointer-form dynamic_cast succeeds for the requested type or an object of a class derived from it.
  • Check the result before using it; nullptr signals that the requested type did not match.
  • Common mistake

    Assuming a void* assignment accepted in C is also accepted in C++.

    What it looks like
    int* p = raw; where raw has type void*.
    Why it fails

    C++ does not allow this implicit conversion.

    Do this instead

    When reviewing C code moved to C++, make the intended conversion explicit.

  • Common mistake

    Assuming a converted pointer proves that the memory contains an object of the new type.

    What it looks like

    Writing through an int* that was obtained from a void* pointing to a character object.

    Why it fails

    The write can reach neighboring bytes that belong to something else.

    Do this instead

    Do not treat the conversion alone as evidence that using the new pointer is safe.

  • Common mistake

    Using a dynamic_cast result without checking whether it is nullptr.

    Why it fails

    A pointer-form dynamic_cast returns nullptr when the pointed-to object is not the requested type or a class derived from it.

    Do this instead

    Test the result before using it as a pointer to the requested type.

Keep the Two Checks Distinct

  1. 1
    C permits assigning a void* to another pointer type without a cast; C++ does not.
  2. 2
    A conversion does not establish that the memory can safely be used as the new type. A write through a mismatched pointer can reach neighboring bytes.
  3. 3
    The source guidance is to cast malloc() results to the right type when using malloc() in C++, and to avoid malloc() in C++-only code.
  4. 4
    A pointer-form dynamic_cast attempts to produce the requested pointer type. It returns nullptr when the object is neither that type nor derived from it.
  5. 5
    Check a dynamic_cast result before using it as a pointer to the requested type.

Key Takeaways

  • C accepts an implicit conversion from void* to another pointer type; C++ requires an explicit conversion.
  • A pointer conversion can lead to writes reaching memory beyond the intended object.
  • Cast malloc() results to the right pointer type when using malloc() in C++, and avoid malloc() in C++-only code.
  • A pointer-form dynamic_cast returns a matching pointer or nullptr.
  • Test the dynamic_cast result before using the pointer.

More concepts starting with C