assigning void * type value

L

LordHog

Hello all,

I am having a little problem getting my (void *) assignment to work
correctly. Basically it is some code for a circular queue buffer I am
trying to implement, but getting the deferrencing of the (void *) type
is giving me problems... For brevity sake not all the functions are
defined, but the name gives a clue to what it does...


[------------Code Begins------------]
#define FAIL 0x01
#define SUCCESS 0x00
typedef unsigned long UINT32;

typedef struct {
void* data[CBQ_MAX_QUEUE_SIZE];
INT8 head,
tail;
} CIRCULAR_BUF_DESCRIPTOR;


STATUS_RESULT_TYPE PopCbq( CIRCULAR_BUF_DESCRIPTOR* QueueDescriptor,
void* objectRef )
{
UINT32 test;
UINT32* testRef;

// Check for valid arguments
if ( QueueDescriptor == NULLPTR || objectRef == NULLPTR ) { return
FAIL; }

// Check to make sure the queue isn't empty first.
if ( IsCbqEmpty(QueueDescriptor) ) { return FAIL; }

test = 0x5555;

testRef = &test;

*testRef = (void *)QueueDescriptor->data[QueueDescriptor->tail++];

// The following line is where I am having the problems... I can get
// the above line to work, but not this one... I am having
indirection
// problems, accoding to Visual C++ v6
*objectRef = (void)QueueDescriptor->data[QueueDescriptor->tail++];

// *objectRef = ((void *)test);

return SUCCESS;
}
[------------Code Ends------------]


So I am not sure what I am doing wrong.. I have tried various
declarations, but none of them work. What am I doing wrong or might be
a better approach? This function is suppose to take care or different
types of data which the application later needs to cast it to the
appropriate data type. Thanks for any help...

Mark
 
P

Peter Nilsson

Hello all,

I am having a little problem getting my (void *) assignment to work
correctly.

Don't cast the right operand of the assignment. The whole purpose
of void * is that you _don't_ need to cast it when assigning to
a compatible pointer type. e.g....

T *p = malloc(N * sizeof *p);
Basically it is some code for a circular queue buffer I am
trying to implement, but getting the deferrencing of the (void *) type
is giving me problems... For brevity sake not all the functions are
defined, but the name gives a clue to what it does...
...
STATUS_RESULT_TYPE PopCbq( CIRCULAR_BUF_DESCRIPTOR* QueueDescriptor,
void* objectRef )
{
UINT32 test;
UINT32* testRef;

// Check for valid arguments
if ( QueueDescriptor == NULLPTR || objectRef == NULLPTR ) { return
FAIL; }

// Check to make sure the queue isn't empty first.
if ( IsCbqEmpty(QueueDescriptor) ) { return FAIL; }

test = 0x5555;

testRef = &test;

*testRef = (void *)QueueDescriptor->data[QueueDescriptor->tail++];

Since testRef is a pointer to an integer, *testRef is an integer
(lvalue). But you try to assign a void pointer, which is an
incompatible type, indeed the code is a constraint violation.

I'm surprise compilation doesn't stop at this line.
// The following line is where I am having the problems... I can get
// the above line to work, but not this one... I am having
indirection
// problems, accoding to Visual C++ v6
*objectRef = (void)QueueDescriptor->data[QueueDescriptor->tail++];

You can't assign void objects.
 
L

LordHog

Peter,

Thanks for the very quick reply, but I am still unclear what I need
to do in order to fix the code. After looking at the post I left
testing code that wasn't suppose to be include, I am very sorry for
this. All the code that uses the following

UINT32 test;
UINT32* testRef;

isn't part of my original problem with trying trying to pop data out
of array (void* data[CBQ_MAX_QUEUE_SIZE] ) and copy it into the input
argument (void* objectRef) of the function
PopCbq().

Since the project that I am working on is embedded there is no use of
dynamic allocation and everything is statically defined or locally
defined within a function. I am not sure if that helps any, but just
some back ground info.

Mark
 
L

Lawrence Kirby

Hello all,

I am having a little problem getting my (void *) assignment to work
correctly. Basically it is some code for a circular queue buffer I am
trying to implement, but getting the deferrencing of the (void *) type
is giving me problems... For brevity sake not all the functions are
defined, but the name gives a clue to what it does...


[------------Code Begins------------]
#define FAIL 0x01
#define SUCCESS 0x00
typedef unsigned long UINT32;

typedef struct {
void* data[CBQ_MAX_QUEUE_SIZE];
INT8 head,
tail;
} CIRCULAR_BUF_DESCRIPTOR;


STATUS_RESULT_TYPE PopCbq( CIRCULAR_BUF_DESCRIPTOR* QueueDescriptor,
void* objectRef )

You need to explain what it is this function is supposed to be doing, and
in particular what is the purpose of the objectRef argument
{
UINT32 test;
UINT32* testRef;

// Check for valid arguments
if ( QueueDescriptor == NULLPTR || objectRef == NULLPTR ) { return
FAIL; }

// Check to make sure the queue isn't empty first. if (
IsCbqEmpty(QueueDescriptor) ) { return FAIL; }

test = 0x5555;

testRef = &test;

*testRef = (void *)QueueDescriptor->data[QueueDescriptor->tail++];

// The following line is where I am having the problems... I can get
// the above line to work, but not this one... I am having
indirection
// problems, accoding to Visual C++ v6 *objectRef =
(void)QueueDescriptor->data[QueueDescriptor->tail++];

// *objectRef = ((void *)test);

It appears that you are trying to return in some way an entry that was in
the datastructure indicated by QueueDescriptor. There are various ways you
can go about this, e.g. return a pointer to the object in the
datastructure or make a copy of the object.

If you want to return a pointer then do that, the easiest way is to make
the return type void * and use some other nethod to return a result code.
You may just be able to return NULL to indicate failure. It is then the
responsibility of the caller to convert the void * pointer to a pointer of
the appropriate type and then use it. You could pass an argument of type
void ** and write a void * value through that, but it is again the
responsibility of the caller to convert the void * value to the correct
type.

If you want to make a copy of the object then you can have the caller
define the destination object and pass a pointer to that for objectRef. It
will also need to pass the size of the object as another argument because
PopCbq just has a void * pointer i.e. it knows nothing about the object
other than its start address in memory. So if you had

STATUS_RESULT_TYPE PopCbq( CIRCULAR_BUF_DESCRIPTOR* QueueDescriptor,
void* objectRef
size_t objectSize)

you might have something like

memcpy(objectRef, QueueDescriptor->data[QueueDescriptor->tail++],
objectsize);

return SUCCESS;
}
[------------Code Ends------------]


So I am not sure what I am doing wrong.. I have tried various
declarations, but none of them work. What am I doing wrong or might be a
better approach? This function is suppose to take care or different
types of data which the application later needs to cast it to the
appropriate data type. Thanks for any help...

You first need to be clear about what it is you are trying to do. And be
aware that there is no polymorphism in C, you can't access an object
through a void * pointer to it, you have to convert the pointer back to an
appropriate type in the code first. You CAN treat any object as an array
of unsigned char if you know its size which is in effect what the memcpy()
call above does.

Lawrence
 
O

Old Wolf

... my original problem with trying trying to pop data out
of array (void* data[CBQ_MAX_QUEUE_SIZE] ) and copy it into the input
argument (void* objectRef) of the function
PopCbq().

C passes parameters by value. You are passing 'objectRef' as a
parameter to a function. This means that the calling function must
pass in a valid pointer to something, and the caller cannot see
any changes that the function makes to 'objectRef'.

If you are trying to return a value via a parameter, then the
parameter needs to be a pointer to what you are trying to
return.

Here's a simple example:
void get_int(int *p) { *p = 5; }
void foo(void) { int x; get_int(&x); }

Now to repeat the example but with (void *) as the type instead
of int:

STATUS_RESULT_TYPE PopCbq(
CIRCULAR_BUF_DESCRIPTOR *QueueDescriptor,
void **objectRef )
{
*objectRef = QueueDescriptor->data[QueueDescriptor->tail++];
return 0;
}

void foo()
{
CIRCULAR_BUF_DESCRIPTOR bar;
...............
void *ptr;
PopCbq(&bar, &ptr);
}

You can then go on to use 'ptr' for whatever purpose (including
converting it back to point to the type it was pointing to
originally).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top