Go Down

Topic: void pointers * something (Read 2035 times) previous topic - next topic

creativen

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

Code: [Select]
#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; ?

tuxduino

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

creativen

#2
Mar 06, 2012, 09:43 am Last Edit: Mar 06, 2012, 09:57 am by creativen Reason: 1
I'm trying to digest it,because I also see there is void* data...hmmm

How about this:

Quote
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?

AWOL

Quote
*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?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

creativen

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.

Nick Gammon

Code: [Select]
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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Plus, the indentation sucks.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

AWOL

Code: [Select]
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?
Code: [Select]
int* pint=(int*)data;
++(*pint);


Quote
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.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Nick Gammon

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


Code: [Select]

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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

tuxduino

@Nick

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

Nick Gammon

Thanks!

In fact you can simplify further with templates:

Code: [Select]
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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

creativen

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/

westfw

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:

Code: [Select]
int *ip = (int *) malloc(sizeof(int));
char *cp = (char *) malloc(UART_BUFFERSIZE);
paktype *packet = (paktype *) malloc(sizeof(paktype));

Nick Gammon


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/


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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

westfw

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.

Go Up