void pointers * something

I am studying about pointer for my arduino project sake, and I found confusion here:
http://www.cplusplus.com/doc/tutorial/pointers/

#include <iostream>
using namespace std;

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}

int main ()
{
  char a = 'x';
  int b = 1602;
  increase (&a,sizeof(a));
  increase (&b,sizeof(b));
  cout << a << ", " << b << endl;
  return 0;
}

what does it mean pchar=(char*)data; ?

what does it mean pchar=(char*)data; ?

(char*)data is an explicit typecast. It temporarily labels data as if it was declared as char* instead of void*. Basically, the compiler won't allow you to assign a void* (pointer to unknown data type) to a char* (pointer to a known data type, a char), because from its point of view, the data at that address (that of a void*) could be anything. You need to tell it you know what you're doing, and force it to treat data as if it pointed to a char.

The fact that nothing can be inferred about what is pointed to by data is made clear by the second argument of increase(), and the way that function is used. The caller tells the function what type data actually points to (well, sort of).

I'm trying to digest it,because I also see there is void* data...hmmm

How about this:

If we write:
*p++ = *q++;
Because ++ has a higher precedence than *, both p and q are increased, but because both increase operators (++) are used as postfix and not prefix, the value assigned to *p is *q before both p and q are increased. And then both are increased. It would be roughly equivalent to:
*p = *q;
++p;
++q;
Like always, I recommend you to use parentheses () in order to avoid unexpected results and to give more legibility to the code.

I dont really get the equivalence between that two..
Could someone help me?

*p++ = *q++;

Break it down:

  1. Fetch what q points to (invisibly call it "temp").
  2. Increment q
  3. Assign "temp" to what p points to.
  4. Increment p

Clearer?

This part is clear for me...
I just think it is not equivalent with this:

*p = *q;
++p;
++q;

here,
1.get the value of q
2. equal it to the value p get
3. the address pointed by p is increased
4. the address pointed by q is increased

if so, it will not give equivalent result as above one.

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}

Personally I think this is extremely dodgy code. If someone working for me wrote it, I would tell them to try again. Rewrite. For one thing, what if psize happens to be 4 (and this is likely on some machines), and both a float and an int could be 4 bytes. So the function basically is not only incomprehensible, it is doomed to fail.

So I wouldn't bother trying to understand it.

Plus, the indentation sucks.

int* pint; pint=(int*)data; ++(*pint);

I really don't understand this style of coding - you've declared a variable, so why not save typing and screen space and initialise it at the same time?

int* pint=(int*)data; 
++(*pint);

if so, it will not give equivalent result as above one.

I don't understand why you think that.
I think you may be confusing the value of a pointer and the value that it points to.

In C++ you can just overload the function. eg.

void increase (int & data)
  {
  data++;
  }

void increase (char & data)
  {
  data++;
  }

void increase (float & data)
  {
  data++;
  }

And so on.

So you need a better example to demonstrate pointers.

@Nick

I totally agree. I’m sure there are better ways to exemplify pointers…

Thanks!

In fact you can simplify further with templates:

template <typename T> void increase (T & data)
  {
  data++;
  }

void setup ()
  {
  float a;
  int b;
  char c;
  long d;
  unsigned long e;
  long long f;

  increase (a);
  increase (b);
  increase (c);
  increase (d);
  increase (e);
  increase (f);
  }
void loop () {}

Now that will handle any (reasonable) type.

Note that this doesn’t compile in the IDE (because of the way the preprocessor works). But it will if you move the templated function into a separate .h file, and include that.

Anw, I am learning the code from here, I am trying to understand so I ask the forum.
http://www.cplusplus.com/doc/tutorial/pointers/

It's supposed to be demonstrating that a void * pointer can point to data of any type, but it's not a very good example.
malloc() is a better test case (not that a c++ programmer would use malloc(), of course.)
malloc(n) returns a void* pointer to a chunk of n bytes of memory, which you would then cast to whatever type was appropriate:

int *ip = (int *) malloc(sizeof(int));
char *cp = (char *) malloc(UART_BUFFERSIZE);
paktype *packet = (paktype *) malloc(sizeof(paktype));

creativen:
Anw, I am learning the code from here, I am trying to understand so I ask the forum.
Pointers - C++ Tutorials

OK, but void pointers are rather esoteric. And thus the examples tend to be confusing. Stick to pointers to real types for now.

By and large you don't need pointers in C++ because you can use references instead. My advice is to keep it simple. Don't waste a lot of time understanding things like void pointers. Just stick to simpler things and get a good grip on them.

I dunno. Void* pointers are easy. They're just an address of some memory. You can't do much of anything with them (other than pass them around) until you've forcefully identified what's in that memory (with a cast.) That makes sense, even at machine code levels.

Now, real pointers are harder, because they're supposed to point to a particular type of thing, but that's really just a fiction that is only enforced by the compiler.

Well, look at it like this. Void pointers are like pointers to atoms. That's only useful if you know how many atoms are in something (like a cat). But a cat* pointer points at a cat. And if you add one, it points to the next cat. You don't have to care how many atoms are in the cat. Now that's useful!

I've never quite been convinced by the need for a void pointer type - a char is by definition the smallest addressable element, so is the smallest thing you can have a pointer to.
I guess void just anonymises (if such a word / verb exists) it.

void pointers aren't overly useful, they are just required. Memory allocation systems don't allocate to a type, but an address with a data range, which is a void pointer. ( explicit 'operator new' over plain old 'new' )

Also before templates were fully formed, people wrote functions like

void DoStuff( void *v_Data, int i_Size )
  {
    //Do stuff
    return;
  }

With the only benefit for using it over typed pointers was to remove casting everything to a standard type. ( Any pointer type can be implicitly cast to void* but not the other way around ).

Also there is this example.

void Foo(void (*fp)(void *), void *q) {
  fp(q);
}

This use of void*allows Foo to take a pointer to a function and handle any type of argument.

but that's really just a fiction that is only enforced by the compiler.

And a darned good thing it (generally) is, too.