(void*)0 : what is this cast?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • alexis4
    New Member
    • Dec 2009
    • 113

    (void*)0 : what is this cast?

    Hello!

    The below sample code is from string.h

    Code:
    #ifndef NULL
    #define NULL    ((void*)0)
    #endif

    What is this void* cast? Under what circumstances can it be used? Can you please give an example or a link reference?

    I thought that I recently saw passing an expression like that as an argument to a function. Is this true?

    Thanks!
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    NULL is used in C as a pointer with a value of 0. That is, a null pointer. void* is a pointer to any type, so (void*)0 is a cast of the integer value 0 to a pointer to any type.

    NULL is not used in C++.

    Comment

    • donbock
      Recognized Expert Top Contributor
      • Mar 2008
      • 2427

      #3
      The void* type has many legitimate uses in C and C++ beyond this one example that you noted.

      The void* type declares a generic pointer variable. Since the compiler doesn't know what you intend to point at with such a variable, it won't let you dereference the pointer. However, you can pass such a pointer to and from functions.

      A C program can use void* pointers to approximate polymorphism and information hiding. C++ probably has better ways to achieve these goals.

      Comment

      • alexis4
        New Member
        • Dec 2009
        • 113

        #4
        Thank you both for your answers.

        The void* type has many legitimate uses in C and C++ beyond this one example that you noted.
        Can you please give me examples of using this or give me references to study this by myself? I am interested on how a type like this can be used as parameter passing. And what is the usage of passing such parameters in functions?

        Please note that I don't use C++, so examples on C is my main interest.

        Thanks again.

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          A void pointer is used in C to make up for the lack of no function overloading. Like this:

          Code:
          void Display(char* c, int number toDsplay);
          void Display(int* c, int number toDsplay);
          void Display(UserData* c, int number toDsplay);
          etc...
          You can have only one Display function so you have to do something like this:
          Code:
          void DisplayChar(char* c, int number toDsplay);
          void DisplayInt(int* c, int number toDsplay);
          void DisplayUserData(UserData* c, int number toDsplay);
          etc...
          which is ugly. So you use a void* argument:
          Code:
          void Display(void* c, int number toDsplay, unsigned int typeid);
          You have one function again but you now have to pass to the function an additional argument that contains a value the function can use to typecast the void* back to the correct type. The big downside is that every time you add a new type to dsplay you need to revise the Display function.

          Comment

          • donbock
            Recognized Expert Top Contributor
            • Mar 2008
            • 2427

            #6
            FYI, the first code snippet is either what you wish you could accomplish or perhaps it is legal C++ code. Only the last two code snippets are legal C code.

            Comment

            • donbock
              Recognized Expert Top Contributor
              • Mar 2008
              • 2427

              #7
              The following header file illustrates how a void* can be used for information hiding. Suppose you create a library of functions in C for dealing with an object (in the OO sense of the word). Your user needs to pass the object to your library functions. You implement the object type to accomplish its user-scope purposes, but also to make your library as efficient as possible. You don't want those pesky users to fool around directly with your object type. Use void* like this and they can't.

              Code:
              void *fooConstructor(void);
              void fooMethod1(void *p, ...);
              void fooMethod2(void *p, ...);
              int fooAttribute1(void *p);
              float fooAttribute2(void *p);
              ... 
              void fooDestructor(void *p);
              Your library functions cast the void* argument to and from a pointer to the actual object type.

              Comment

              • alexis4
                New Member
                • Dec 2009
                • 113

                #8
                OK thank you both again, that made sence... So I wrote the below peace of dummy code:

                Code:
                void function1 (void *ptr);
                uint8 a = 10;
                uint8 *p;
                
                void main (void)
                {
                  p = &a;	
                  function1(p);
                }
                
                void function1 (void *ptr)
                {
                  uint8 *pp;
                  pp = (uint8 *)ptr;
                  (*pp)++;
                  pp = NULL;
                }
                The result at the end of function1() was:
                *p = a = 11, and pointer pp dereferenced (if this terminology is correct but you get the idea).

                So about my last "dark spot". I understood about function overloading, but regarding information hiding:

                The following header file illustrates how a void* can be used for information hiding ... Use void* like this and they can't.
                You gave your explanation donbock, but I didn't quite understand it (and I am terribly sorry about that). When you say "object" in C, you mean structures with function pointers in its members, correct? What must be protected? I mean take your own example:

                Code:
                void fooMethod1(void *p, ...);
                If I know for sure that p is int type (this means that there is no need for function overloading), then why wouldn't I write it as

                Code:
                void fooMethod1(int *p, ...);
                What am I protecting with the first way of function declaration?

                If my dummy code isn't dummy enough to explain, feel free to expand this example.

                Thanks!

                Comment

                • donbock
                  Recognized Expert Top Contributor
                  • Mar 2008
                  • 2427

                  #9
                  When I said object I meant ... some arbitrary type that you have decided to only access through functions. It need not contain function pointers.

                  What must you protect? Anything and everything that you, as designer, have decided should not be directly accessed by the users. If you, as designer, don't care if the users access the object type directly then nothing needs to be hidden.

                  Comment

                  • alexis4
                    New Member
                    • Dec 2009
                    • 113

                    #10
                    Thanks once more donbock. I got the idea, but I missed the technical explanation. How can

                    void fooMethod1(void *p, ...);

                    protect my data accessed inside fooMethod1, while

                    void fooMethod1(int *p, ...);

                    cannot?

                    Comment

                    • donbock
                      Recognized Expert Top Contributor
                      • Mar 2008
                      • 2427

                      #11
                      The advantage of using a void* for information hiding is more obvious when the object type is a structure. In that case, use of the void* prevents the user from accessing the structure members directly. That leaves you free to delete or rename members as the library evolves.

                      There are advantages even when the object type is an int. By hiding access to the int you force the user to use the access functions in your library. That leaves you free to alter the scaling or units of the object type. Your access functions can also implement business rules to ensure consistency within and among objects.

                      Among the disadvantages of this approach is the performance penalty of making a function call instead of accessing the object directly. Not only does the function call and return add overhead, but diverting to another function interferes with the optimizer. Another disadvantage is the function namespace pollution caused by creating names for all those access functions.

                      Comment

                      • alexis4
                        New Member
                        • Dec 2009
                        • 113

                        #12
                        Thank you donbock, all seems much more clear now!

                        Comment

                        Working...