Thread: casting - pointer to pointer

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

    Question Example Of Char **

    Code:
    int main( )
    {
      char *words[ ] = { "Then",   "he",   "shouted", "What", "I",
                        "didn't", "hear", "what",    "you",  "said" };
      int j = 0;
      int n = sizeof(words) / sizeof(char *);
    
      qsort( words, n, sizeof(char *), strptrcmp );
    
      for ( j = 0 ; j < n ; j++ )
        puts( words[j] );
    }
    
    int strptrcmp( const void *sp1, const void *sp2 )
    // Compare two strings by reference.
    {
      // qsort( ) passes a pointer to the pointer:
      // dereference it to pass a char * to strcmp.
      const char * s1 = *(char **)sp1;
      const char * s2 = *(char **)sp2;
      return strcmp( s1, s2 );
    }
    When I compile this code as
    Code:
    const char *s1 = *(char *) sp1;
    const char *s2 = *(char *) sp2;
    I get the compiler error...

    initialization makes pointer from integer without a cast

    What does it mean?

  2. #32
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Really? I get no warning or error at all.
    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.

  3. #33
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    const char *s1 = *(char *) sp1;
    const char *s2 = *(char *) sp2;
    Yes, of course, you are dereferencing *(char *)sp1, which is a char - so the compiler can automatically convert that to a int, but it complains that you are trying to convert that integer to a pointer, because you should have a cast when you do that. In this case, you want two stars to make it pointer to a char *, so that you can dig out the original pointer to the word that is currently being sorted.

    --
    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.

  4. #34
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Oh, I didn't realize the big code and the small code was different. Of course the example snippet doesn't work. Dereferencing a char* gets you char, which is not char* (what you're trying to assign to).
    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.

  5. #35
    Registered User
    Join Date
    Apr 2008
    Posts
    31

    Question

    Quote Originally Posted by matsp View Post
    Code:
    const char *s1 = *(char *) sp1;
    const char *s2 = *(char *) sp2;
    so the compiler can automatically convert that to a int, but it complains that you are trying to convert that integer to a pointer, because you should have a cast when you do that. In this case, you want two stars to make it pointer to a char *, so that you can dig out the original pointer to the word that is currently being sorted. --
    Mats
    Can you "simplify" a bit what you just said.
    It's bouncing in my head...
    Why would compiler convert it to an "int", where in the code am I converting integer to a pointer? Also, I am using casting.

  6. #36
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    > It's bouncing in my head...

    Okay, let's rehash what we know:
    void pointers can be assigned to any type.
    To dereference a void pointer (*), you have to cast it to a type first.

    in const char *s1 = *(char*) sp1;

    (char*) is the cast, and to the left of that is the dereference. Since the result of dereferencing a char* is basically a integral type, the compiler complains as integers are not a pointer type.

    There's a syntactical misunderstanding here that becomes a bigger problem.

  7. #37
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by terminator View Post
    Can you "simplify" a bit what you just said.
    It's bouncing in my head...
    Why would compiler convert it to an "int", where in the code am I converting integer to a pointer? Also, I am using casting.
    Right, if we break down your original statement:
    const char *s1 = *(char *) sp1;
    The orange is a variable declaration of a char pointer variable called s1.
    The green star means "dereference the pointer" - which means "take whatever the pointer points at". The red says "Make this next thing into a char *". And the blue is your void pointer coming into this function.

    So, the green bit says, "take whatever this points to", which the red bit says is a char pointer, so it becomes a char (becuase the green bit removes one pointer level). Then stuff that into a char pointer called s1.

    The compiler will, as part of it's "helpfulness" convert your char to an integer - but then complain that it's not a pointer.

    --
    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.

  8. #38
    Registered User
    Join Date
    Apr 2008
    Posts
    31

    Question

    Quote Originally Posted by citizen View Post
    > It's bouncing in my head...

    Okay, let's rehash what we know:
    void pointers can be assigned to any type.
    To dereference a void pointer (*), you have to cast it to a type first.

    in const char *s1 = *(char*) sp1;

    (char*) is the cast, and to the left of that is the dereference. Since the result of dereferencing a char* is basically a integral type, the compiler complains as integers are not a pointer type.

    There's a syntactical misunderstanding here that becomes a bigger problem.
    Ahh... this guy is a good guy.
    But wait... what's the meaning of "integral type"?

    Also, dereferencing char* gives a char which is NOT a "string", but just a character, i.e. first character of a string. Right?

  9. #39
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Integral type is all "integer types", anything that can hold whole numbers, such as "int", "short", "char", "long" and "enum types".

    Non-integral types include "float", "double", any pointers, structs and unions (and classes in C++ of course).

    --
    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.

  10. #40
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by iMalc View Post
    Even Dave_Sinkula seems to have misunderstood this one, going by his first comment - Must be having an off day.
    Probably.
    Quote Originally Posted by Dave_Sinkula View Post
    In C, there is probably little reason for any cast at all.
    Code:
    int strptrcmp( const void *sp1, const void *sp2 )
    {
       const char *const * s1 = sp1;
       const char *const * s2 = sp2;
       return strcmp( *s1, *s2 );
    }
    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.*

  11. #41
    Registered User
    Join Date
    Apr 2008
    Posts
    31

    Question

    dereferencing char* gives a char which is NOT a "string", but just a character, i.e. first character of a string. Right?

  12. #42
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    dereferencing char* gives a char which is NOT a "string", but just a character, i.e. first character of a string. Right?
    Yes.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #43
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by terminator View Post
    dereferencing char* gives a char which is NOT a "string", but just a character, i.e. first character of a string. Right?
    Yes - dereferencing ANY pointer gets you "one less star", so "char *" becomes "char", and "char ****" becomes a "char ***".

    And yes, that'd be the first character of the string.

    --
    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. #44
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    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);
    You could do the same thing without the casts like this:
    Code:
    int compare (const void *p1, const void *p2)
    {
      const char **ptr1 = p1;
      const char **ptr2 = p2;
      const char *i;
      const char *j;
    
      i = *ptr1;
      j = *ptr2;

  15. #45
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by swoopy View Post
    You could do the same thing without the casts like this:
    Code:
    int compare (const void *p1, const void *p2)
    {
      const char **ptr1 = p1;
      const char **ptr2 = p2;
      const char *i;
      const char *j;
    
      i = *ptr1;
      j = *ptr2;
    or even:
    [code]
    Code:
    int compare (const void *p1, const void *p2)
    {
      const char **ptr1 = p1;
      const char **ptr2 = p2;
      const char *i = *ptr1;
      const char *j = *ptr2;
    --
    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.

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