tags:

views:

126

answers:

5
typedef struct _DListNode
{
    struct _DListNode* prev;
    struct _DListNode* next;
    void*  data;
}DListNode;

in gcc :

DListNode *p = NULL;

p = (DListNode*)malloc(sizeof(DListNode));

p->data = (int*)malloc(sizeof(int));   

scanf("%d", (int*)p->data);

compile correctly.

in gcc :

DListNode *p = NULL;

p = (DListNode*)malloc(sizeof(DListNode));

(int*)p->data = (int*)malloc(sizeof(int)); 

scanf("%d", (int*)p->data);

There is a problem on :

(int*)p->data = (int*)malloc(sizeof(int)); -------error: lvalue required as left operand of assignment.

the difference:

scanf("%d", (int*)p->data) ,

(int*)p->data = (int*)malloc(sizeof(int)),

p->data = (int*)malloc(sizeof(int));
+2  A: 

The difference between the statements is that it doesn't make sense to try and specify the pointer type on the left-hand-side of an expression which is what you're doing in the (int*)p->data case because p->data is always a void* as defined in the structure. When the compiler sees this it assumes you're casting it to an int* so that you can read it, i.e. it becomes an r-value, a value which is only valid on the right-hand-side of an assignment expression not an l-value (left-hand-side) which can be assigned to.

If you want to read / write an integer value stored in p->data then I think the clearest syntax is *((int*)(p->data)) - i.e. take the p->data pointer, cast it to an int* and then dereference that - but I'm sure you can lose some of the brackets due to the precendence rules.

data is a void pointer; it doesn't care what you store in it, i.e. your (int*) cast on the malloc is effectively wasted; it only cares that you've given it some allocated memory.

Rup
Thanks for everyone answering my question. "(int*)p->data case because p->data is always a void* as defined in the structure", I just wander that if I want to store an int value into a unit, I have to use "scanf("%d", (int*)p->data) ", use (int *)to specify.so, why there is no need to use (int*) to specify or tell the "p->data", hey, what you are store is a pointer vale of int*.
albertxiaoyu
+1  A: 

How about (int*&)p->data = (int*)malloc(sizeof(int));"?

(int *) gives the pointer value itself, i.e. it's akin to saying 0x12345678 = malloc(sizeof(int));.

Btw, mallocing for something as small as an int is extremely wasteful.

EDIT:

  1. This might only work in C++, not C.

  2. Why do you cast in the first place? You're assigning a void pointer to a void pointer. Isn't that convenient? Why cast?

  3. If you really want to amuse yourself, you could do something silly like *(int **) &(p->data) = (int *) malloc(sizeof(int));. Nonsense, right? Right. Just assign the value. Better yet, replace your data with a union.

EboMike
That won't work, and if it worked, it would only work in C++, not C.
Zack
It does work in C++, my C is a bit rusty. I don't see the point of casting in the first place anyway.
EboMike
Zack
It is, it's basically a reference to the pointer, so you can modify it. Again, this whole approach is kind of backwards to begin with. There shouldn't be a cast, and there preferably shouldn't be a malloc.
EboMike
A: 

type cast() has high Precedence than ->, so your first one is equal to ((int*)p)-data. I think that's not what you want.

Tristan Su
+2  A: 

Is there a good reason to have a void* instead of an int* in struct _DListNode? If not, change it to int* and then you don't need any of the casts. It's always better to make the types be correct in the first place than to sprinkle casts all over your code.

The error you're getting is because you simply cannot put a cast on the left side of an assignment. It's against the rules. You need to read up on what lvalues and rvalues are and what the difference between them is.

Zack
A: 

So, what is your question? And what is that "the difference" section supposed to mean?

So far, you've got the problem with

(int*)p->data = (int*)malloc(sizeof(int));

which is obviously an invalid statement. The compiler has already told you why.

So, once again, what is your question?

AndreyT