void * vs char *

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Francine.Neary@googlemail.com

    #1

    void * vs char *

    I've been reflecting on these two types of pointer. As far as I can
    glean from books, void * and char * are functionally equivalent: the
    key property of both is that they are pointers that can be faithfully
    cast to any other pointer type.

    The only difference seems to be that it is legal to perform arithmetic
    on a char *, but not on a void *.

    So if a char * really is just a more functional void *, why would
    anyone ever use a void * in their code, instead of a char *?

  • pete

    #2
    Re: void * vs char *

    Francine.Neary@ googlemail.com wrote:
    >
    I've been reflecting on these two types of pointer. As far as I can
    glean from books, void * and char * are functionally equivalent: the
    key property of both is that they are pointers that can be faithfully
    cast to any other pointer type.
    >
    The only difference seems to be that it is legal to perform arithmetic
    on a char *, but not on a void *.
    >
    So if a char * really is just a more functional void *, why would
    anyone ever use a void * in their code, instead of a char *?
    The sole purpose of void*
    is to reduce the amount of casts in a program.
    Most pointer conversions to and from void* can be done without a cast.
    Most other pointer conversions require a cast.

    Before the invention of type void, char* was used instead.

    --
    pete

    Comment

    • Ian Collins

      #3
      Re: void * vs char *

      Francine.Neary@ googlemail.com wrote:
      I've been reflecting on these two types of pointer. As far as I can
      glean from books, void * and char * are functionally equivalent: the
      key property of both is that they are pointers that can be faithfully
      cast to any other pointer type.
      >
      The only difference seems to be that it is legal to perform arithmetic
      on a char *, but not on a void *.
      >
      So if a char * really is just a more functional void *, why would
      anyone ever use a void * in their code, instead of a char *?
      >
      To avoid casting every assignment of something other than a char* to and
      from a char*.

      --
      Ian Collins.

      Comment

      • Richard Tobin

        #4
        Re: void * vs char *

        In article <1174262593.153 711.146610@n59g 2000hsh.googleg roups.com>,
        <Francine.Neary @googlemail.com wrote:
        >So if a char * really is just a more functional void *, why would
        >anyone ever use a void * in their code, instead of a char *?
        char * means that it points to characters or bytes. void * doesn't;
        it means that it points to something of unspecified type. Even if
        there was no functional difference between them, it would be
        worthwhile to be able to express your intent.

        -- Richard



        --
        "Considerat ion shall be given to the need for as many as 32 characters
        in some alphabets" - X3.4, 1963.

        Comment

        • Keith Thompson

          #5
          Re: void * vs char *

          pete <pfiland@mindsp ring.comwrites:
          Francine.Neary@ googlemail.com wrote:
          >>
          >I've been reflecting on these two types of pointer. As far as I can
          >glean from books, void * and char * are functionally equivalent: the
          >key property of both is that they are pointers that can be faithfully
          >cast to any other pointer type.
          >>
          >The only difference seems to be that it is legal to perform arithmetic
          >on a char *, but not on a void *.
          >>
          >So if a char * really is just a more functional void *, why would
          >anyone ever use a void * in their code, instead of a char *?
          >
          The sole purpose of void*
          is to reduce the amount of casts in a program.
          Most pointer conversions to and from void* can be done without a cast.
          Most other pointer conversions require a cast.
          No, that's not the *sole* purpose.

          The problem with a char* is that you can't tell whether it's intended
          to be a generic pointer (in pre-C89 code), or a pointer to actual
          character data, or a pointer to a small integer (or an array thereof),
          or a pointer to byte data (or an array thereof). The ANSI committee
          invented void* to give us a generic pointer type, one that has the
          advantage that you can't accidentally dereference it and obtain a
          possibly meaningless char value.
          Before the invention of type void, char* was used instead.
          Yes.

          --
          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
          San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
          "We must do something. This is something. Therefore, we must do this."
          -- Antony Jay and Jonathan Lynn, "Yes Minister"

          Comment

          • Francine.Neary@googlemail.com

            #6
            Re: void * vs char *

            On Mar 19, 12:11 am, Ian Collins <ian-n...@hotmail.co mwrote:
            To avoid casting every assignment of something other than a char* to and
            from a char*.
            I don't really follow this argument about minimizing number of casts.
            For example, the following code fails - I still need to explicitly
            cast p to a (struct s*) to avoid a compile-time error.

            #include <stdio.h>

            void call(void *);
            struct s { int a; };

            main()
            {
            struct s a;
            a.a=1234;
            call(&a);
            return 0;
            }

            void call(void *p)
            {
            printf("%d\n",p->a);
            }

            --
            Ian Collins.

            Comment

            • Ian Collins

              #7
              Re: void * vs char *

              Francine.Neary@ googlemail.com wrote:
              On Mar 19, 12:11 am, Ian Collins <ian-n...@hotmail.co mwrote:
              >
              >>To avoid casting every assignment of something other than a char* to and
              >>from a char*.
              >
              I don't really follow this argument about minimizing number of casts.
              For example, the following code fails - I still need to explicitly
              cast p to a (struct s*) to avoid a compile-time error.
              >
              No, you don't.
              #include <stdio.h>
              >
              Let's start by making it legal C:
              void call(void *);
              struct s { int a; };
              >
              main()
              int main(void)
              {
              struct s a;
              a.a=1234;
              call(&a);
              return 0;
              }
              >
              void call(void *p)
              {
              printf("%d\n",p->a);
              struct s *ps = p;
              printf("%d\n",p s->a);
              }
              >
              Now change call to

              void call( char* );

              And see what your compiler has to say. If you don't get two
              incompatible type warnings, you haven't turned your warning level high
              enough.

              --
              Ian Collins.

              Comment

              • Flash Gordon

                #8
                Re: void * vs char *

                Flash Gordon wrote, On 19/03/07 10:10:

                <snip>
                > printf("%d\n",p->a);
                struc s *sp = p;
                A perfect example of why I should have copied and pasted even a small
                example, not retyped on a different computer. That should have been
                struct not struc, of course.
                --
                Flash Gordon

                Comment

                • Flash Gordon

                  #9
                  Re: void * vs char *

                  Francine.Neary@ googlemail.com wrote, On 19/03/07 09:28:
                  On Mar 19, 12:11 am, Ian Collins <ian-n...@hotmail.co mwrote:
                  >To avoid casting every assignment of something other than a char* to and
                  >from a char*.
                  >
                  I don't really follow this argument about minimizing number of casts.
                  For example, the following code fails - I still need to explicitly
                  cast p to a (struct s*) to avoid a compile-time error.
                  >
                  #include <stdio.h>
                  >
                  void call(void *);
                  struct s { int a; };
                  >
                  main()
                  {
                  struct s a;
                  a.a=1234;
                  call(&a);
                  No cast here that I can see, but if call took a char* as a parameter one
                  would be required.
                  return 0;
                  }
                  >
                  void call(void *p)
                  {
                  printf("%d\n",p->a);
                  struc s *sp = p;
                  printf("%d\n",s p->a);

                  Now it works since you are translating back to a compatible (the
                  original) type and not a cast in sight.
                  }
                  Also as a side note it would be better to be explicit about main
                  returning an int, especially as C99 has dropped implicit int. Best to be
                  specific about not taking parameters as well.
                  int main(void)
                  --
                  Flash Gordon

                  Comment

                  • pete

                    #10
                    Re: void * vs char *

                    Francine.Neary@ googlemail.com wrote:
                    >
                    On Mar 19, 12:11 am, Ian Collins <ian-n...@hotmail.co mwrote:
                    To avoid casting every assignment of something other than a char* to and
                    from a char*.
                    >
                    I don't really follow this argument about minimizing number of casts.
                    For example, the following code fails - I still need to explicitly
                    cast p to a (struct s*) to avoid a compile-time error.
                    >
                    #include <stdio.h>
                    >
                    void call(void *);
                    struct s { int a; };
                    >
                    main()
                    {
                    struct s a;
                    a.a=1234;
                    call(&a);
                    return 0;
                    }
                    >
                    void call(void *p)
                    {
                    printf("%d\n",p->a);
                    }
                    The problem is that you have used the (void *) type badly.

                    The prototype of the call function
                    void call(void *p);
                    indicates that it is intended
                    to take a pointer to any type object.
                    But it isn't intended to take a pointer to any type object.
                    The printf call statement, shows that p must be a pointer
                    to a struct with a member "a" of type int.
                    The right way to write that program is:

                    /* BEGIN new.c */

                    #include <stdio.h>

                    struct s {
                    int a;
                    };

                    void call(struct s* p);

                    int main(void)
                    {
                    struct s a;

                    a.a = 1234;
                    call(&a);
                    return 0;
                    }

                    void call(struct s *p)
                    {
                    printf("%d\n", p->a);
                    }

                    /* END new.c */

                    mem_cpy is an example of a function that uses
                    void * type parameters more better.

                    void *mem_cpy(void *s1, const void *s2, size_t n)
                    {
                    unsigned char *p1 = s1;
                    const unsigned char *p2 = s2;

                    while (n-- != 0) {
                    *p1++ = *p2++;
                    }
                    return s1;
                    }


                    --
                    pete

                    Comment

                    • Francine.Neary@googlemail.com

                      #11
                      Re: void * vs char *

                      On Mar 19, 10:39 am, Ian Collins <ian-n...@hotmail.co mwrote:
                      Francine.Ne...@ googlemail.com wrote:
                      On Mar 19, 12:11 am, Ian Collins <ian-n...@hotmail.co mwrote:
                      >
                      >To avoid casting every assignment of something other than a char* to and
                      >from a char*.
                      >
                      I don't really follow this argument about minimizing number of casts.
                      For example, the following code fails - I still need to explicitly
                      cast p to a (struct s*) to avoid a compile-time error.
                      >
                      No, you don't.
                      >
                      #include <stdio.h>
                      >
                      Let's start by making it legal C:
                      >
                      void call(void *);
                      struct s { int a; };
                      >
                      main()
                      int main(void)
                      ???

                      main() is perfectly valid C - it defines main to be a function taking
                      no arguments and returning int. You may have a personal preference for
                      the more verbose form, but that doesn't make it invalid. I've borrowed
                      a copy of the ANSI Standard from the library, so now I too can quote
                      chapter & verse :)
                      >From 6.3.2.2:
                      If the expression that precedes the parenthesized argument list in a
                      function call consists solely of an identifier, and if no declaration
                      is visible for this identifier, the identifier is implicitly declared
                      exactly as if, in the innermost block containing the function call,
                      the declaration
                      extern int identifier();
                      appeared.

                      and from 6.5.4.3:
                      An empty list in a function declarator that is part of a definition of
                      that function specifies that the function has no parameters.

                      (For reference, it continues: The empty list in a function declarator
                      that is not part of
                      a definition of that function specifies that no information about the
                      number or types of the parameters is supplied.)
                      void call(void *p)
                      {
                      printf("%d\n",p->a);
                      >
                      struct s *ps = p;
                      A rose by any other name... I don't see that this gains anything in
                      terms of clarity or brevity over "printf("%d\n", ((struct s*)p)->a);" -
                      in fact it just leads to an additional pointer floating around.
                      Now change call to
                      >
                      void call( char* );
                      >
                      And see what your compiler has to say. If you don't get two
                      incompatible type warnings, you haven't turned your warning level high
                      enough.
                      As this conversion is lossless, I don't see why the compiler should
                      take it upon itself to warn me about it!
                      --
                      Ian Collins.

                      Comment

                      • Keith Thompson

                        #12
                        Re: void * vs char *

                        Francine.Neary@ googlemail.com writes:
                        On Mar 19, 10:39 am, Ian Collins <ian-n...@hotmail.co mwrote:
                        >Francine.Ne... @googlemail.com wrote:
                        On Mar 19, 12:11 am, Ian Collins <ian-n...@hotmail.co mwrote:
                        >>
                        >>To avoid casting every assignment of something other than a char* to and
                        >>from a char*.
                        >>
                        I don't really follow this argument about minimizing number of casts.
                        For example, the following code fails - I still need to explicitly
                        cast p to a (struct s*) to avoid a compile-time error.
                        >>
                        >No, you don't.
                        >>
                        #include <stdio.h>
                        >>
                        >Let's start by making it legal C:
                        >>
                        void call(void *);
                        struct s { int a; };
                        >>
                        main()
                        >int main(void)
                        >
                        ???
                        >
                        main() is perfectly valid C - it defines main to be a function taking
                        no arguments and returning int. You may have a personal preference for
                        the more verbose form, but that doesn't make it invalid. I've borrowed
                        a copy of the ANSI Standard from the library, so now I too can quote
                        chapter & verse :)
                        >
                        >>From 6.3.2.2:
                        If the expression that precedes the parenthesized argument list in a
                        function call consists solely of an identifier, and if no declaration
                        is visible for this identifier, the identifier is implicitly declared
                        exactly as if, in the innermost block containing the function call,
                        the declaration
                        extern int identifier();
                        appeared.
                        [...]

                        I think you're looking at a copy of the 1990 standard. C99 dropped
                        implicit int.

                        Yes, "main()" is legal in C90 (Ian was partly mistaken on that point),
                        but in my opinion "int main(void)" is better.

                        [...]
                        >Now change call to
                        >>
                        >void call( char* );
                        >>
                        >And see what your compiler has to say. If you don't get two
                        >incompatible type warnings, you haven't turned your warning level high
                        >enough.
                        >
                        As this conversion is lossless, I don't see why the compiler should
                        take it upon itself to warn me about it!
                        Because char* is not (since 1989) a generic pointer type, and a
                        warning is likely to tell you about a logical error in your code. In
                        fact, since there is no implicit conversion from struct s* to char*,
                        the call is a constraint violation; the compiler *must* issue a
                        diagnostic, and it *may* reject the program altogether.

                        You seem to be arguing that the compiler should shut up about implicit
                        conversions that don't lose any information; in other words, you want
                        C's type checking to be even weaker than it is. You're certainly
                        entitled to that opinion, but it's not one many people share. If you
                        want a generic pointer type, use void*. There are plenty of
                        mechanisms that let you be sloppy with types if you do it
                        deliberately; *I* want the compiler to warn me if I do it
                        accidentally.

                        --
                        Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                        San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
                        "We must do something. This is something. Therefore, we must do this."
                        -- Antony Jay and Jonathan Lynn, "Yes Minister"

                        Comment

                        • Richard Heathfield

                          #13
                          Re: void * vs char *

                          Francine.Neary@ googlemail.com said:
                          On Mar 19, 10:39 am, Ian Collins <ian-n...@hotmail.co mwrote:
                          >Francine.Ne... @googlemail.com wrote:
                          <snip>
                          #include <stdio.h>
                          >>
                          >Let's start by making it legal C:
                          >>
                          void call(void *);
                          struct s { int a; };
                          >>
                          main()
                          >int main(void)
                          >
                          ???
                          >
                          main() is perfectly valid C - it defines main to be a function taking
                          no arguments and returning int.
                          Agreed. (In C99, it has to be int main() at the very least, but in C90
                          main() is legal.)
                          You may have a personal preference for
                          the more verbose form,
                          Yes. Adding the return type makes it C99-conforming, and using the
                          prototype form is good style, but these are choices, not requirements.

                          <snip>
                          void call(void *p)
                          {
                          printf("%d\n",p->a);
                          >>
                          > struct s *ps = p;
                          >
                          A rose by any other name... I don't see that this gains anything in
                          terms of clarity or brevity over "printf("%d\n", ((struct s*)p)->a);" -
                          in fact it just leads to an additional pointer floating around.
                          Nevertheless, it represents a considerable gain in correctness over
                          printf("%d\n", p->a), wouldn't you agree?

                          --
                          Richard Heathfield
                          "Usenet is a strange place" - dmr 29/7/1999

                          email: rjh at the above domain, - www.

                          Comment

                          • Francine.Neary@googlemail.com

                            #14
                            Re: void * vs char *

                            On Mar 19, 7:35 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
                            Nevertheless, it represents a considerable gain in correctness over
                            printf("%d\n", p->a), wouldn't you agree?
                            Well, yes :)

                            The whole point of that example was that it was code that used a void
                            * but wouldn't compile unless you added in an explicit cast.
                            --
                            Richard Heathfield
                            "Usenet is a strange place" - dmr 29/7/1999http://www.cpax.org.uk
                            email: rjh at the above domain, - www.

                            Comment

                            • Ian Collins

                              #15
                              Re: void * vs char *

                              [...]
                              >
                              I think you're looking at a copy of the 1990 standard. C99 dropped
                              implicit int.
                              >
                              Yes, "main()" is legal in C90 (Ian was partly mistaken on that point),
                              but in my opinion "int main(void)" is better.
                              >
                              Where I'm sitting, C == C99 :)

                              --
                              Ian Collins.

                              Comment

                              Working...