Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

void pointer

Status
Not open for further replies.

hughLg

Programmer
Feb 18, 2002
136
MY
in C, we can use the untyped pointer (void *) to represent general pointer that can be converted from and to other pointer type. however, can I access the value stored in a address pointed to by a void pointer like other normal pointer assignment:

int i = 3, i1 = 8,
int *ip = &i;

*ip = 5;
i1 = *ip;

why do I can't do like this with void pointer?

I want to write a function that deal with general data type by using void pointer and returns back the correct result. e.g. to write a function that will takes 1 void pointer as parameter and returns void value. after execute inside this function, I have to assign it into completed type pointer. I can do this well. but the problem is how can I determine what data type it should be converted to. if I declare and define all available data type in this function, it's seems a bad idea and it's also impossible. because the return value can only be one. how can I choose...

and the another things, I can use operator sizeof to determine address size to be converted to. but different data type may have the same size.
 
Hi,

First, you can not use the value pointed by a void pointer because you explicitly tell the compiler to forget what is pointed by this pointer. Before using the pointed value you have to explicitly tell the compiler what it is: I mean cast the void pointer to a non void pointer and dereferenced it (like this
Code:
*((int *)myVoidPtr)
).

For the function now.
AFAIK you can not do that easily in C.
What you need is one or more of:
[ul][li]polymorphism,
[li]function overloading,
[li]templates.[/ul]
Try C++.

In C you have to give the generic function the type of object pointed by void* (or a way to find it like the %fields of format string in *scanf functions) and you have to explicitly cast the return value. #define can help you, though.
The sizeof is of no use because:
Code:
sizeof((void *)&anInt) == sizeof((void *)&aDouble)
    == sizeof((void *)&anyStructYouWant) == 4
and
Code:
sizeof(*((void *)&anyType)) == 1 /* if even allowed */

Try the following code to check this:
Code:
#include <stdio.h>
#define PRINTVARANDVALUE(var, type)     printf(#var &quot; = <&quot; type &quot;>\n&quot;, var)

int
main(int argc, char *argv[])
{
  int i = 12345;
  double d = 1.23456;

  void *pi = &i,
       *pd = &d;

  PRINTVARANDVALUE(sizeof(i), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(d), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(pi), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(pd), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(*pi), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(*pd), &quot;%d&quot;);

  return 0;
}

My output is:
Code:
sizeof(i) = <4>
sizeof(d) = <8>
sizeof(pi) = <4>
sizeof(pd) = <4>
sizeof(*pi) = <1>
sizeof(*pd) = <1>


So below is one example of a function taking a void *, casting it and returning a new void * to the same type, but I do not believe it is a good practice. Avoid it if you do not know exactly what you do. There is many pitfall (use of static local variable, no more compilation check available about variable types, ...).

Code:
#include <stdio.h>
typedef enum
  {
    isChar, isShort, isInt, isFloat, isDouble
  }  myTypes;

void *
myGenericFunction(void *ptr, myTypes type)
{
  switch (type)
    {
    case isInt:
      {
	static int i;
	i = *((int *)ptr) + 1; /* For example */
	return &i;
      }
    case isDouble:
      {
	static double d;
	d = *((double *)ptr) + 1; /* For example */
	return &d;
      }
      /* And so on */
    }
  return (void *)NULL;
}

#define myGenericFunctionInt(p)      (*(int *)myGenericFunction(p, isInt))
#define myGenericFunctionDouble(p)     (*(double *)myGenericFunction(p, isDouble))
/* And so on */

#define PRINTVARANDVALUE(var, type) printf(#var &quot; = <&quot; type &quot;>\n&quot;, var)
int
main(int argc, char *argv[])
{
  int i = 12345;
  double d = 1.23456;

  void *pi = &i, *pd = &d;

  PRINTVARANDVALUE(sizeof(i), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(d), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(pi), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(pd), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(*pi), &quot;%d&quot;);
  PRINTVARANDVALUE(sizeof(*pd), &quot;%d&quot;);

  PRINTVARANDVALUE(myGenericFunctionInt(&i), &quot;%d&quot;);
  PRINTVARANDVALUE(myGenericFunctionInt(pi), &quot;%d&quot;);
  PRINTVARANDVALUE(myGenericFunctionDouble(&d), &quot;%lf&quot;);
  PRINTVARANDVALUE(myGenericFunctionDouble(pd), &quot;%lf&quot;);

  return 0;
}

Again my output:
Code:
sizeof(i) = <4>
sizeof(d) = <8>
sizeof(pi) = <4>
sizeof(pd) = <4>
sizeof(*pi) = <1>
sizeof(*pd) = <1>
myGenericAddInt(&i) = <12346>
myGenericAddInt(pi) = <12346>
myGenericAddDouble(&d) = <2.234560>
myGenericAddDouble(pd) = <2.234560>
 
Denniscpp,

A pointer is an address which references memory (usually virtual memory). Bytes in memory are organized in a linear fashion by their addresses starting with byte 0 (address 0) and ending with byte N (N is very large). So an address is an unsigned integer. If the address is '4' then it references the fourth byte in memory (if we start at the zeroth byte). All of the variables you declare in your program are stored somewhere in memory. As you have mentioned, it is often convenient to know the address of a variable or structure. This is what the '&' operator does. It returns the address of the variable which is called a pointer in C. This is why all pointer are of the same size. So if our variable is a float, declaring a pointer of float * tells the compiler to interpret the data at that address as a float (whether it is or not). Likewise for the other types. A void pointer is a pure address. It says that we do not know or care about the contents of a memory location, only its location. Void pointer are often use to implement type independent routines like you are atempting to do (for an example, see the qsort() routine) or when manipulating generic memory (e.g. malloc, bzero, memset, shmat). Because the type void has a size of zero, you must never index or increment a void pointer. For example:

Code:
void *genPtr ;
float myArray[] = {1, 2, 3} ;
float thirdNumber ;

genPtr = myArray ;
thirdNumber = (float)genPtr[2] ;  /* BAD: do not do this */

Also, be very careful when returning a value from a function by reference (i.e. via pointer). This is frequent source of nasty bugs. If you do, do not return a local variable. If you return the address of a static variable, make sure the function does not re-enter.

Mark.
 
Hi,

I need help on buffer cleaning.

What I mean is:
Once I fill the buffer with
Code:
strcpy(buff, &quot;xyz\r&quot;)
and next time I need the
Code:
buff
to be empty with nothing inside it. How do I do that?

Actually, first time I need to write
Code:
xyz
in the buffer and next time only
Code:
xy
and then I need to compare the buffer with an ASCII character 'ACK'. So, if the buffer is not cleaned I cann't compare the two.

Thanks in advance.
 
to empty the character buffer you can either memset it or

*buff = 0;


the memset will change the whole buffer but the *buff = 0 puts the null terminator at the beginning and is all you need for a zero lenght string.

Matt
 
Sorry, didn't get what is this memset.

In the second case, do I need to create some pointer first and then initialise it during clearing?

What I do now is to loop whole of array to
Code:
'\0'
. But this gives something really silly when I want to know the value of the buffer content (something like '
Code:
0Y-#
', cann't type with the keyboard, I think some unprintable characters).

XMahle
 
Another way for clearing a buffer is simply using this:

strcpy(buff, &quot;&quot;); /*this will clear the buffer*/
 
If you want to actually zero the entire contents of the buffer you use memset like this:

something *buffer;
.....
memset(buffer, 0, buffer_size);

This sets buffer_size number of bytes to 0 starting with the one pointed to bu buffer.

If you use it as a string, and thus only have to put a zero length string in it to &quot;clear&quot; it, the easiest way is to do as Zyrenthian said above:
*buffer = 0;
or
buffer[0] = 0;
 
what about if i want to define a function deal with general data type by using void pointer, even with array, and structure type?

because i want to write a set of link list functions that can deal with general types. i.e. push and pop node with different data type in data field. such as use these functions to push int data, float, array, structure data into list list node...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top