#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    2
    Rep Power
    0

    Need a C equivalent for C++ dynamic_cast


    Looking for a way in C to recast a pointer to a different data type or structure dynamically like dynamic_cast in C++. Can this be done in C with void * or something similar??

    Also can an array of C pointers have different types assigned by recasting somehow? If so how to do in C?

    I basically want a pointer to behave as a pointer to a different data type or different structure actually depending on the value of a parameter. This will allow me to read a buffer region differently depending on the contents and its structure.

    Thanks!
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,175
    Rep Power
    2222
    Very simple: use type-casting.

    If you type-cast a variable to another data type, then the value will be retained but will now be in the now type's format; eg:

    unsigned char Byte = 0x80; // one byte long
    int i = (int)Byte; // now two bytes long

    float fl = 1.5f;
    int trunct = (int)fl; // has been truncated to a value of 1


    To keep from messing up the size of the data, use pointers and typecast from one type of pointer to another.

    For example, I recently experiment with creating an unsigned long integer and then listing the value of each individual byte:

    Code:
        unsigned long ulIP;
        unsigned char *cp;
        char address[80];
    
        cp = (unsigned char*)&ulIP;
    
        // convert dotted-decimal to network-order address
        ulIP = inet_addr(address);
        printf("%s --> %d.%d.%d.%d\n",address,*cp,*(cp+1),*(cp+2),*(cp+3));
    I took the address of ulIP, which would be an (unsigned long*) and typecast it as (unsigned char*) in order to assign it to a variable of that type.

    You can also do something like:
    int i = *((int*)&some_long_int);

    Hope that helps.
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,175
    Rep Power
    2222
    My C++ work was just before the re-standardization a half-decade or so ago, so I wasn't very familiar with dynamic casting.

    Looking it up on-line, it appears to be very C++-specific in that it depends on run-time type identification and works on classes derived from the same base class. C has neither feature.

    My guess would be that you will need to write a different function for each struct type and test explicitly which one to call.

    A real-life example might be the sockaddr structure in sockets programming. struct sockaddr is just a generic struct that has an ID (sa_family) as its first element and an array of bytes to fill the remainder. Then for TCP/IP you use a struct sockaddr_in which has the same initial ID field, which tags the address structure as being of a specific type. All sockets functions that take an address are written to take a struct sockaddr pointer, so you write the function call to cast your pointer to a sockaddr_in as a (struct sockaddr*).

    Hope that helps. If it doesn't, then perhaps a short example of what you're trying to do would help us help you better.
  6. #4
  7. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    2
    Rep Power
    0
    Thanks dwise, but not exactly what I want to do.

    I want something dynamic like this:

    Code:
    typedef struct {float a[1]; float b;} MY_STRUCT1;
    typedef struct {float a[2]; float b;} MY_STRUCT2;
    
    float databuffer [1000];
    
    void *variableStructPtr;
    
    if (numElementsInA == 1)
        variableStructPtr = (MY_STRUCT1 *) &(databuffer[0]);
    else
        variableStructPtr = (MY_STRUCT2 *) &(databuffer[0]);
    .
    .
    .
    Then access the structure components variableStructPtr->a[i] and
    variableStructPtr->b to extract data from a buffer in different ways depending on what is in the buffer, but I want to do it with a single variable pointer...

    In other words, I want to change the behavior and the type of the pointer itself. Can this be done in C by some means (maybe something cast to a "void" pointer and then cast the "void" pointer into something else)??
    Last edited by SLSTEK@Work; February 13th, 2003 at 03:19 PM.
  8. #5
  9. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,640
    Rep Power
    4247
    Originally posted by SLSTEK@Work
    In other words, I want to change the behavior and the type of the pointer itself. Can this be done in C by some means (maybe something cast to a "void" pointer and then cast the "void" pointer into something else)??
    Yep, that would be one way to do it. All you have to do is pass some kind of int value or something like that, so that the other end knows how to typecast the void pointer back to the proper struct.

    If you look at the sockets API, you'll notice that the socket functions accept a structure of type sockaddr and other extra parameters. However, for actual coding, the programmer usually uses a sockaddr_in or sockaddr_in6 or whatever. When passing the structure to the socket functions, the programmer typecasts the variable to type sockaddr so the function will accept it.

    Now if you look at the definitions of the structures, the first three or four members of struct sockaddr, sockaddr_in, sockaddr_in6 etc. are the same name and type. So the function can look at the sockaddr.ss_family field and determine the actual type of pointer that this should be. Then it typecasts the pointer back accordingly and accesses the remaining members that are unique to that structure type. This way, you only have one function that accepts a sockaddr type, instead of defining multiple functions that do the same thing, but accepting sockaddr_in, sockaddr_in6 etc.
    http://www.experts-exchange.com/Prog..._20337039.html

    Hope this helps!
    Last edited by Scorpions4ever; February 13th, 2003 at 06:04 PM.
  10. #6
  11. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    2
    Rep Power
    0
    Ahhhhh -- Nice info and link Scorpions4ever and very similar to what I am looking to try to do; will have to examine and unravel that sockets API and see what they are doing inside; probably a switch + case select probably to recast according to the common "ss_family" structure member...

    The problem I was/am having in trying to use a generic void * type definition and then a recast, was that the a compile time error indicated incorrect void type for the expression on the selection operator, but for a global parameter definition. Will experiment with a local function variable with internal recasting within each case selection and see what happens.

    Thanks a bunch guys!
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2002
    Posts
    272
    Rep Power
    19
    You could also read up on the use of unions in almost any C book.
  14. #8
  15. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    2
    Rep Power
    0
    Yes -- unions is definitely a nice feature for variable access and use for other things (good sections in both K&R new text and H&S's C: A Reference Manual), but want to try to get the variable pointer method to work with casting, but not exactly the way I had hoped. I can also access the data via brute force with ++ operators and looping, which would be faster most likely too. I use unions to access data optionally as unsigned, integer, or floats in some cases when buffers contain different data types and is very nice too, plus do lots of casting with dynamic memory with malloc, realloc, etc. I was just wanting to generalize it with a single pointer with a single name and use selections operators and see if performance is adequate.

IMN logo majestic logo threadwatch logo seochat tools logo