Typecasting of pointers in C

62,495

Solution 1

A program well written usually does not use much pointer typecasting. There could be a need to use ptr typecast for malloc for instance (declared (void *)malloc(...)), but it is not even necessary in C (while a few compilers may complain).

  int *p = malloc(sizeof(int)); // no need of (int *)malloc(...)

However in system applications, sometimes you want to use a trick to perform binary or specific operation - and C, a language close to the machine structure, is convenient for that. For instance say you want to analyze the binary structure of a double (that follows thee IEEE 754 implementation), and working with binary elements is simpler, you may declare

  typedef unsigned char byte;
  double d = 0.9;
  byte *p = (byte *)&d;
  int i;
  for (i=0 ; i<sizeof(double) ; i++) { ... work with b ... }

You may also use an union, this is an exemple.

A more complex utilisation could be the simulation of the C++ polymorphism, that requires to store the "classes" (structures) hierarchy somewhere to remember what is what, and perform pointer typecasting to have, for instance, a parent "class" pointer variable to point at some time to a derived class (see the C++ link also)

  CRectangle rect;
  CPolygon *p = (CPolygon *)&rect;
  p->whatami = POLY_RECTANGLE; // a way to simulate polymorphism ...
  process_poly ( p );

But in this case, maybe it's better to directly use C++!

Pointer typecast is to be used carefully for well determined situations that are part of the program analysis - before development starts.

Pointer typecast potential dangers

  • use them when it's not necessary - that is error prone and complexifies the program
  • pointing to an object of different size that may lead to an access overflow, wrong result...
  • pointer to two different structures like s1 *p = (s1 *)&s2; : relying on their size and alignment may lead to an error

(But to be fair, a skilled C programmer wouldn't commit the above mistakes...)

Best practice

  • use them only if you do need them, and comment the part well that explains why it is necessary
  • know what you are doing - again a skilled programmer may use tons of pointer typecasts without fail, i.e. don't try and see, it may work on such system / version / OS, and may not work on another one

Solution 2

In plain C you can cast any pointer type to any other pointer type. If you cast a pointer to or from an uncompatible type, and incorrectly write the memory, you may get a segmentation fault or unexpected results from your application.

Here is a sample code of casting structure pointers:

struct Entity { 
  int type;
}

struct DetailedEntity1 {
  int type;
  short val1;
}

struct DetailedEntity2 {
  int type;
  long val;
  long val2;
}

// random code:
struct Entity* ent = (struct Entity*)ptr;

//bad:
struct DetailedEntity1* ent1 = (struct DetailedEntity1*)ent;
int a = ent->val; // may be an error here, invalid read
ent->val = 117; // possible invali write

//OK:
if (ent->type == DETAILED_ENTITY_1) {
  ((struct DetailedEntity1*)ent)->val1;
} else if (ent->type == DETAILED_ENTITY_2) {
  ((struct DetailedEntity2*)ent)->val2;
} 

As for function pointers - you should always use functions which exactly fit the declaration. Otherwise you may get unexpected results or segfaults.

When casting from pointer to pointer (structure or not) you must ensure that the memory is aligned in the exact same way. When casting entire structures the best way to ensure it is to use the same order of the same variables at the start, and differentiating structures only after the "common header". Also remember, that memory alignment may differ from machine to machine, so you can't just send a struct pointer as a byte array and receive it as byte array. You may experience unexpected behaviour or even segfaults.

When casting smaller to larger variable pointers, you must be very careful. Consider this code:

char* ptr = malloc (16);
ptr++;
uint64_t* uintPtr = ptr; // may cause an error, memory is not properly aligned

And also, there is the strict aliasing rule that you should follow.

Share:
62,495
user1871762
Author by

user1871762

Updated on July 09, 2022

Comments

  • user1871762
    user1871762 almost 2 years

    I know a pointer to one type may be converted to a pointer of another type. I have three questions:

    1. What should kept in mind while typecasting pointers?
    2. What are the exceptions/error may come in resulting pointer?
    3. What are best practices to avoid exceptions/errors?
  • unwind
    unwind over 11 years
    I think this is oversimplifying things a bit ... You can't freely cast between function pointers and pointers to data objects for instance. Also, there's no guarantee you'll get a seg fault.
  • WhozCraig
    WhozCraig over 11 years
    I concur with @unwind. One of the worst things about pointer-casting in C is the fundamental idea itself; you're wanting to treat something as if it were something it isn't. With the exception of opaque hiding through void * (aka qsort() type work, and even there the specifics are size-based which you must supply), it is generally good to avoid it entirely. Finally one of the more subtle problems (and the source of big headaches), is data alignment, and isn't mentioned at all.
  • Dariusz
    Dariusz over 11 years
    @WhozCraig Thanks for reminding about data alignment. Though it isn't exactly an issue in pointer casting, mentioning it may be useful.
  • WhozCraig
    WhozCraig over 11 years
    @DariuszWawer it is an enormous issue if the address being stored in the 'cast-to' pointer who's type requires stricter alignment than the data address it now holds complies with (i.e. casting an unsigned char* on an odd-memory address to a float * will bus-error on many platforms as soon as you dereference the float ptr), so we'll have to disagree about that.
  • Dariusz
    Dariusz over 11 years
    @WhozCraig Hey, I'm sensing some flustration or anger in your comment. I'm doing my best here. I added info from you to the answer. Thanks very much:)
  • Olivier Dulac
    Olivier Dulac over 11 years
    I do miss having a central place to look/update things at ... Now the knowledge is spread over several websites, and some have very mistaken answers too... Anyone knows if there is a good (ie "the one everyone should go to") FAQ wiki site?
  • WhozCraig
    WhozCraig over 11 years
    @DariuszWawer Not at all, sir. I only bring up alignment because it is without a doubt the one place casting has bit me the worst in the past. Its a hard question to answer and cover all bases. I assure you I would have down-voted if I thought the answer was totally off-target. You're fine, and no, no anger or frustration to be found =P