Thread: casting - pointer to pointer

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    31

    Cool casting - pointer to pointer

    Can anyone look at the code below and answer the question given in the code...

    Code:
    int compare (const void *p1, const void *p2)
    {
      const char *i;
      const char *j;
    
      i = *((char **)p1); /* WHAT THE HECK IS THIS*/
      j = *((char **)p2);/*Why is the '*' operator 3 times in a line */
    
      if (strlen(i) > strlen(j))
        return 1;
      else if (strlen(i) < strlen(j))
        return -1;
      else
        return strcmp(i,j);
    }

  2. #2
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Its casting a void pointer to a char pointer pointer (pointer to pointer to char), then dereferencing that to get a char pointer that represents a string.

    A char pointer pointer can also be looked at as a pointer to a string. So it's casting void to string pointer, and dereferencing that to get the actual string to compare.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    31

    Post

    Quote Originally Posted by King Mir View Post
    A char pointer pointer can also be looked at as a pointer to a string. .
    Can you give an example on this?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by terminator View Post
    Can you give an example on this?
    Sure:
    Code:
    int compare (const void *p1, const void *p2)
    {
      const char *i;
      const char *j;
    
      i = *((char **)p1); 
      j = *((char **)p2);
    
      if (strlen(i) > strlen(j))
        return 1;
      else if (strlen(i) < strlen(j))
        return -1;
      else
        return strcmp(i,j);
    }
    ((char **)p1) is a pointer to a string; the * in front dereferences it to get the actual string itself. Notice i is of type "const char *" -- the char * means string, more or less (nitpickingly honest: a pointer to a character, but strlen and strcmp are going to interpret it as a pointer to the first character of a series) and the const means that those characters can not be altered.

  5. #5
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I can't see why that code is unnecessarily complicated?
    Instead of:
    Code:
    *((char **)p1)
    wouldn't this be much simpler?
    Code:
    (char *)p1
    or to be const-correct:
    Code:
    (const char *)p1

  6. #6
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Quote Originally Posted by cpjust View Post
    I can't see why that code is unnecessarily complicated?
    Instead of:
    Code:
    *((char **)p1)
    wouldn't this be much simpler?
    Code:
    (char *)p1
    or to be const-correct:
    Code:
    (const char *)p1
    Of course its easier. But only in the same sense as its easier to write

    Example
    Code:
    int j;
    
    for(;j < 5; j++)
    {
    
    }
    Example
    Code:
    int j;
    
    scanf("&#37;d", j);
    Man those sure saved me a whole lot of typing. Too bad my code is invalid. Lets use some typedefs (I know how much Elysa hates them but oh well).

    Code:
    typedef char **type1;
    typedef char *type2;
    Ok, this isn't the best type name convention, however it paints the picture I am wanting you to see. A type1 is certainly not a type2, right? In fact, a type1 is a pointer to a type2.

    Code:
    int compare(const void *a, const void *b)
    {
       // void* can be ANYTHING. But today we want the void pointer to be a type2.
       type1 xptr = (type1)a;
       type1 yptr = (type1)b;
    
       // Remembering that xptr and yptr are both pointers to type2 objects we need to remember
       // to compare what they point to.
       type2 x = *xptr;
       type2 y = *yptr;
    
       // do whatever here.
    }
    I hope that helps. And to clear up one issue for Dave, its ok to do without casting when it comes to a void*, but not a void**. So int *j = malloc(5) is cool. But int **j = malloc(5) requires a cast. I hope that helps too.

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by cpjust View Post
    I can't see why that code is unnecessarily complicated?
    Instead of:
    Code:
    *((char **)p1)
    wouldn't this be much simpler?
    Code:
    (char *)p1
    or to be const-correct:
    Code:
    (const char *)p1
    Nope, the second one is completely wrong. You can't subtract the *'s. This function is obviously being used as an argument to qsort which is to sort an array of char*'s a.k.a strings.

    Original code: The *'s in the cast itself don't do anything besides tell the compiler what type of thing the void pointer is supposed to be. This doesn't generate any code whatsoever. The outer star on the left actually tells the compiler to dereference the thing on the right. That means asking the compiler to generate code that fetches what is at some memory address, and viola you have correct code. There is no simpler way to do this. It must cast to a char**!

    Your incorrect code: The single char* cast tells the compiler (incorrectly) that the data is already a char pointer. This in itself generates no code at all. It does not look up and memory address to get the correct pointer value, and will produce non-working code.

    Even Dave_Sinkula seems to have misunderstood this one, going by his first comment - Must be having an off day.
    King Mir has a good explanation.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    In C, there is probably little reason for any cast at all.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  9. #9
    Registered User
    Join Date
    Apr 2008
    Posts
    31
    Is there any good book or website covering this complex pointer declarations & casting?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Apr 2008
    Posts
    31
    Quote Originally Posted by Elysia View Post
    there is only little explanation about pointer to pointer...
    Is there any good book or website with examples?

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by terminator View Post
    there is only little explanation about pointer to pointer...
    Is there any good book or website with examples?
    It's simple. If you need to modify a pointer (a variable of type type*) in another function then you must pass the variable by pointer, so if the type is type* (pointer), then the new type you would need the function to take is type** (a pointer to type type*).
    For example if you wish to allocate memory via malloc into a variable stored in main (a normal variable can't hold an address, so you need to pass a pointer!).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Pointer to pointer is nothing "special". All pointer variables hold the address of something else. A pointer to pointer is just a variable that hold the address of a pointer - it's really no different from any other pointer. Here's an example:
    Code:
    int x = 7;
    int *px = &x;        // px contains the address of x. 
    int **ppx = &px;    // ppx contains the address of px. 
    int y = 5; 
    int *py = &y;
    
    **ppx = 8;   // Changes x to 8
    
    *ppx = py;  // Now px points to py
    **ppx = 9;   // y is now set to 9.
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    If you fully understand pointers, understanding pointers-to-pointers should be no problem.

    Pointers only hold an address to something else, think of it like man pointing to something. Consider the following, let man = pointer.

    Code:
    [man 0] -> [man 1] -> [man 2] -> [the man you want]
    You want to remember where [the man you want] is,
    * so you tell man 2 to remember where he is,
    * you tell man 1 to remember where man 2 is
    * you tell man 0 to remember where man 1 is

    If you want to find [the man you want] you can either,
    1. ask man 0 where man 1 is (see 2.)
    2. ask man 1 where man 2 is (see 3.)
    3. ask man 2 where [the man you want] is.

    You can of course skip to 2 or 3 or even straight to the man.

    I hope my corny example made it clear

  15. #15
    Registered User
    Join Date
    Apr 2008
    Posts
    31

    Arrow char ** for void type?

    Quote Originally Posted by zacs7 View Post
    If you fully understand pointers, understanding pointers-to-pointers should be no problem.

    Pointers only hold an address to something else, think of it like man pointing to something. Consider the following, let man = pointer.

    Code:
    [man 0] -> [man 1] -> [man 2] -> [the man you want]
    You want to remember where [the man you want] is,
    * so you tell man 2 to remember where he is,
    * you tell man 1 to remember where man 2 is
    * you tell man 0 to remember where man 1 is

    If you want to find [the man you want] you can either,
    1. ask man 0 where man 1 is (see 2.)
    2. ask man 1 where man 2 is (see 3.)
    3. ask man 2 where [the man you want] is.

    You can of course skip to 2 or 3 or even straight to the man.

    I hope my corny example made it clear

    I already know all of the above but, what's the use of (char **)???
    p1 & p2 are pointers to "VOID"...
    Do we have to use (char **) casting for all the "VOID" argument types? or does it depend on the arguments passed to the function?


    Code:
    int compare (const void *p1, const void *p2)
    {
      const char *i;
      const char *j;
    
      i = *((char **)p1); //IF p1 & p2 are strings... what am I doing here?
      j = *((char **)p2);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. casting contents of pointer?
    By nutsNguts in forum C Programming
    Replies: 8
    Last Post: 11-10-2008, 11:07 AM
  2. Ban pointers or references on classes?
    By Elysia in forum C++ Programming
    Replies: 89
    Last Post: 10-30-2007, 03:20 AM
  3. scope of a pointer?
    By Syneris in forum C++ Programming
    Replies: 6
    Last Post: 12-29-2005, 09:40 PM
  4. Question About Pointer To Pointer
    By BlitzPackage in forum C++ Programming
    Replies: 2
    Last Post: 09-19-2005, 10:19 PM
  5. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM