void* to an array

This program gives the following error : lvalue required as increment operand.
1
2
3
4
5
6
7
8
9
10
int main (){
 int a[] = {1,3,4,6};
 void *ref ;
 ref = &a ;
 cout << "\nElements of the array ";
    for(int i=0 ; i < 4 ; i++){
        cout << "\n" << *(((int*)ref)++);
    }
    return 0 ;
}


If I declare one integer pointer and cast the void* to it , it works.
1
2
3
4
5
6
7
8
9
10
11
int main (){
  int a[] = {1,3,4,6};
  void *ref ;
  ref = &a ;
  int * ptr = (int*)ref ;
  cout << "\nElements of the array ";
  for(int i=0 ; i < 4 ; i++){
      cout << "\n" << *(ptr++);
  }
    return 0 ;
}


Is there any way to make it work by NOT using int* ptr ?
Lose the & sign before a... It is an array so it is ( almost ) a pointer.. a points to the first element of the array...
I guess
void* ptr = a ;
and
void* ptr = &a ;
is the same thing !! Please correct me if I am wrong ?

I tried doing like "ptr = a" and it says "lvalue required " as in first case.
Does that mean that void pointer has to be type casted and stored within a object pointer (like int* , float* , double* etc) to access the elements of the object as done in the second program in my first post?
Last edited on
thing one,
1
2
3
void* ptr =a; //and
void* ptr = &a; //are not the same thing.
//a is pointer to integer but &a is pointer to pointer to integer (read int**) 


thing two
1
2
3
4
5
6
7
8
9
10
//the ++ operator requires lvalue (read variable)
//you can do like
int somevar = 5;
somevar++;

//but you can't do lke
int somevar = 5;
(somevar + 1)++;
//why? because somevar+1 is a rvalue. some temporary value created due to the result
//of somevar+1, so ++ can't be used here.. 


thing three, your code, I assume that you are trying to display all the items of your array.
Here's what you can do.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Your original code and the error associated with it
int main (){
 int a[] = {1,3,4,6};
 void *ref ;
 ref = &a ;
 cout << "\nElements of the array ";
    for(int i=0 ; i < 4 ; i++){
        cout << "\n" << *(((int*)ref)++);  // (int*)ref is an rvalue.. yep.
    }
    return 0 ;
}

//the solution, IDK. since you don't want to use int*, your only option will be to increment
//the ref pointer which is a void*. But ISO C++ standard doesn't allow the increment of void*
//at least that's what my compiler told me. Why would you want to not use int* ? And why are
//you using such complex procedures for enumerating arrays? just playing i assume..
The difference between a and &a is the type.

a is of type int[4], which can be implicitly cast to int* (ie, a pointer to an int)
&a is of type int(*)[4] (ie: a pointer to an array of 4 ints).

However even though their types are different, the address is going to be the same. And when assigning to a void pointer, all type information is lost. So in that case, yes...

void* ptr = a;
and
void* ptr = &a;

work out to be exactly the same.


Does that mean that void pointer has to be type casted and stored within a object pointer (like int* , float* , double* etc) to access the elements of the object as done in the second program in my first post?


Yes. void pointers cannot be dereferenced. If you want to access the data they point to, you must cast them to something else.


Really, void pointers should probably be avoided. Using them basically throws all type information out the window which makes them very error prone. If the data is going to be pointing to ints, then use an int* instead of a void*. Save yourself some headaches and plus you don't have to cast as much.
I guess
void* ptr = a ;
and
void* ptr = &a ;
is the same thing !! Please correct me if I am wrong ?


no!

example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;

int main (){
	int *a = new int();
	*a = 3;

	void *p;

	p = &a;
	cout << *((int*)p) << "\n" ;

	p = a;
	cout << *((int*)p) << "\n" ;

	return 0;
}


10834336
3


when you add the & it gives the address of the pointer...
you get a pointer to the pointer a...

But in your example there seems to be no difference.. i do not really get that...;)....

and about the lvalue... it seems you do need the temporary variable..

but you could do it like this:

cout << "\n" << ((int*)ref)[i];

that way you don't need the extra variable...
Last edited on
thanks guys for replying .
yeah , I am just brushing up the basics..
however the thing about a and &a seems a bit NOT clear .

a refers to the address of the first element of the array ie &a[0] , Isn't it ?
This means that a is a pointer to the first element of the integer array ie pointer to an int . Since a is a pointer to an integer , it can be cast like
int* something = a ; and to access the elements of a , we simply do
1
2
3
4
5
*(something+0) // first element
*(something+1) // second element
*(something+2 )// third element
*(something +3)// fourth element
*(something+i)//   (i+1)th element 


&a should refer to the address(memory location) of a ie pointer to a which further points to the int . In other words , pointer to pointer to int .
and I am still trying to understand int(*)[4]
I hope what I understood is not wrong..
try this:
1
2
3
4
5
6
7
8
9
10
int main (){
 int a[] = {1,3,4,6};
 void *ref ;
 ref = a ;
 cout << "\nElements of the array ";
    for(int i=0 ; i < 4 ; i++){
        cout << "\n" << *((reinterpret_cast<int*&>(ref))++);
    }
    return 0 ;
}

it should work, becouse I use int*&, which is an lvalue reference, instead of just int*, which is an rvalue.
Raman009 wrote:
however the thing about a and &a seems a bit NOT clear .

Read what Disch wrote, his answer is pretty much spot-on

a refers to the address of the first element of the array ie &a[0] , Isn't it ?
a is an array. When used as an argument to a function or operator that doesn't accept arrays, but accepts pointers, &a[0] is substituted by the compiler, which first constructs a nameless temporary pointer to the first element, and then passes that pointer to the function/operator by value.

&a should refer to the address(memory location) of a ie pointer to a which further points to the int . In other words , pointer to pointer to int .

No, on two counts:

First, even if the address-of operator didn't work with arrays, this would resolve to &(&a[0]), which would attempt to produce the address of a nameless temporary pointer constructed by the expression &a[0]. But since nameless temporaries have no addresses, this &(&a[0]) doesn't even compile.

Second, since the address-of operator actually does work with arrays, &a simply constructs a pointer to the array a.

and I am still trying to understand int(*)[4]

That is the type of the pointer to an array of 4 ints.
I am still trying to understand int(*)[4]


Yeah pointer to array syntax is funky. Typedef's might make it more clear:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// typedef 'int4' as an array of 4 ints:
typedef int int4[4];

// With that typedef, the below two lines are equivalent:
int a[4] = {1,2,3,4};
int4 a = {1,2,3,4};

// now, 'a' without its brackets is an array name, which means you can assign it to an int4
//   reference:
int4& ref = a;     // OK
int (&ref)[4] = a; // same thing with alternate syntax (without the typedef)

// array names can also be implicitly cast to a pointer to their first element:
int* ptr = a;      // OK
int* ptr = &a[0];  // same thing, also OK


// now if you take '&a', that is not a pointer to an int, but rather a pointer to an array:
int4* ap = &a;      // OK, &a is a pointer to an 'int4'
int (*ap)[4] = &a;  // same thing with alt. syntax (without the typedef)


// now, since void* throws all type information away, you can assign any kind of pointer
//  to it.  'ptr' and 'ap' above are both pointers.  They point to different types, but
//  void* doesn't care about that:
void* vp = ptr;  // OK, ptr is a pointer:  int*
void* vp2 = ap;  // also OK, ap is a pointer:  int4*
void* vp3 = a;   // OK, a can be implicitly cast to a pointer


// Since pointers point to the start of the memory for a given variable, a pointer to an
//  array and a pointer to the first element of the array start at the same memory location
//  so their addresses will be the same:
void* x = a;   // casting int4 to int* to void*
void* y = &a;  // casting int4* to void*

assert( x == y );  // x == y because the memory for an array starts at its first element 
thanks a lot guys ,
typedef 's made it easier to understand
things are certainly more clear now ...
Topic archived. No new replies allowed.