473,395 Members | 1,641 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

warning: dereferencing `void *' pointer

I have some functions which take as i/p a buffer (it can be float, char,
or 16 bit, int etc.). The result is another o/p buffer, its type is also
flexible (it could be a float, char etc.).

I try to pass both as "void *buf" so that it can accept any data type.
But since I access the buffer and try to assign its elements to another
I get compile errors (I have pasted at the end).

Now my question is how can I pass the i/p and o/p buffers as args to the
function without hardcoding the data type, someone earlier suggested to
pass another argument which tells the type, e.g.
myfunction(void * buf, 1, ...) 1 may indicate that buf is char type, 2
means 16 bit etc.

But that means having if .. else's inside the function to do the same
thing. Is there any other way?
Maybe this is not possible in C.
Pushkar Pradhan
resample.c: In function `resample':
resample.c:26: warning: dereferencing `void *' pointer
resample.c:26: warning: dereferencing `void *' pointer
resample.c:26: invalid use of void expression
resample.c:35: warning: dereferencing `void *' pointer
resample.c:35: warning: dereferencing `void *' pointer
resample.c:35: invalid use of void expression

Nov 14 '05 #1
4 16083
In article <3F**************@gri.msstate.edu>
Pushkar Pradhan <pu*****@gri.msstate.edu> writes:
I have some functions which take as i/p a buffer (it can be float, char,
or 16 bit, int etc.). The result is another o/p buffer, its type is also
flexible (it could be a float, char etc.).

I try to pass both as "void *buf" so that it can accept any data type.
But since I access the buffer and try to assign its elements to another
I get compile errors (I have pasted at the end).

Now my question is how can I pass the i/p and o/p buffers as args to the
function without hardcoding the data type, someone earlier suggested to
pass another argument which tells the type, e.g.
myfunction(void * buf, 1, ...) 1 may indicate that buf is char type, 2
means 16 bit etc.

But that means having if .. else's inside the function to do the same
thing. Is there any other way?


Here is a bit pattern, 32 bits long:

11000101001110101001110101000110

What does it mean? What value(s) does it represent?

Does your answer change if I tell you it is the raw bits of a 32-bit
"float"? What if I say it is a 32-bit VAX float, or perhaps a 32-bit
SPARC float? Suppose I say it is, instead, a 32-bit "int", or a
32-bit "signed int". Now what value(s) can it represent? What if
it is an array of four "char"s or four "unsigned char"s?

(Finding answers -- there may be more than one -- to the above
questions is a good and useful exercise, that will help you understand
how the system(s) you use interpret bits. Note that different
systems interpret the same bits differently! One reason we use
"high level" source code -- although C is relatively low level for
a high level language -- is to avoid having to specify the precise
set of bits, which change from system to system, when we can get
away with specifying only what we want the bits to mean. The
source-code number "3.1415" or "42" has a definite meaning, and
the fact that machines A and B use different bit-patterns to
represent them is -- we hope -- irrelevant.)

Note that all of these are 32 bits long. They all look exactly the
same when treated as a 32-bit-long bit-string. But they all represent
different values.

When you use "void *" in C, you are -- usually -- implicitly using
a "bag of uninterpreted bits" type. Any interpretation necessarily
arises from giving the "bag of bits" some more-specific type. You
must decide whether you intend to interpret the bits, and if so, how.
This will dictate the type(s) you must provide.

Note that a series of if/else's, or a switch, inside a function
that receives a "void *" but wants to interpret the bits as one
of (say) the two possibilities "int" and "float" will result in C
code looking like:

enum whichtype { TY_INT, TY_FLOAT };
/*
* Here p points to the first bit(s) in the bag-o-bits, "len"
* is the number of items of some interpreted type, and "ty"
* is the enumeration saying which type.
*/
void f(void *p, size_t len, enum whichtype ty) {
size_t i;
int *ip;
float *fp;

switch (ty) {
case TY_INT:
ip = p;
... work with ip[i], where i is between 0 and len-1, e.g:
for (i = 0; i < len; i++)
ip[i] *= 2;
break;

case TY_FLOAT:
fp = p;
... work with fp[i], where i is between 0 and len-1 ...
for (i = 0; i < len; i++)
fp[i] *= 2.0;
break;

default:
panic("invalid type argument %d to f()", (int)ty);
/* NOTREACHED */
}
}

Not only do you really, truly have to write the if/else or switch,
you will also find that, on typical machines, it compiles to code
that uses different machine instructions to manipulate the data.
The code using ip[i] might look like, e.g.:

# this doubles ip[i], where i is in %eax and ip is in %edx
movl (%edx,%eax,4),%ecx
addl %ecx,%ecx
movl %ecx,(%edx,%eax,4)

versus:

# this doubles fp[i], where i is in %eax and fp is in %edx
flds (%edx,%eax,4)
fadds (%edx,%eax,4)
fstps (%edx,%eax,4)

These completely-different machine instructions are utterly necessary
here -- using the "addl %ecx,%ecx" instructions will not result in
doubling a "float" value in fp[i], but rather will just make a mess
of the value.

Thus, different C code is required because different machine code
is required. Using "void *" absolves neither you nor the compiler
of this.

If you do enough of this sort of thing (or analyse your systems
carefully), you will find that there are cases where the C source
code must be different, yet the underlying machine code on your
machine(s) is the same. This happens because (and when) the abstract
meaning defined in C for two different types happens to be implemented
using a single underlying machine-level mechanism. But in general,
the C code should remain separate, because on some *other* machine(s),
this may no longer be the case. In other words, in the C code,
you write *what* you want to have happen, not *how* to *make* it
happen. If you want different things, at the C level, that all
happen to be done the same way at the machine level, it is the
compiler's job to discover this and optimize the code appropriately.
(Some compilers are better than others at this, and you may sometimes
find yourself having to "help" some compilers a bit. Do this only
when you really know what you are doing. :-) )
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #2
Pushkar Pradhan wrote:

I have some functions which take as i/p a buffer (it can be float, char,
or 16 bit, int etc.). The result is another o/p buffer, its type is also
flexible (it could be a float, char etc.).

I try to pass both as "void *buf" so that it can accept any data type.
But since I access the buffer and try to assign its elements to another
I get compile errors (I have pasted at the end).

Now my question is how can I pass the i/p and o/p buffers as args to the
function without hardcoding the data type, someone earlier suggested to
pass another argument which tells the type, e.g.
myfunction(void * buf, 1, ...) 1 may indicate that buf is char type, 2
means 16 bit etc.

But that means having if .. else's inside the function to do the same
thing. Is there any other way?
Maybe this is not possible in C.


It depends on exactly what your are trying to do with the buffer.
If you wanted to do something simple,
like reverse the order of the elements,
it could be done this way:

#include <stddef.h>
void some_functions(void *buf, size_t nmemb, size_t size)
{
unsigned char *first = buf;
unsigned char *last = (nmemb - 1) * size + first;
unsigned char *p1, *p2, swap, *end;

while (last > first) {
p1 = last;
p2 = first;
end = p2 + size;
do {
swap = *p1;
*p1++ = *p2;
*p2++ = swap;
} while (p2 != end);
last -= size;
first += size;
}
}

If your function is going to do something very different,
for each different data type that the buffer may contain,
then you'll need something like a switch;
perhaps an ifelse tree, or an array of function pointers.

qsort has this prototype:

#include <stdlib.h>
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));

The arguments base, nmemb and size,
tell qsort everything that it needs to know about the array.
The compar pointer, tells qsort exactly how to deal with the array.

If your function
is going to do something different with each data type,
then you can pass it a function pointer also,
in a manner similar to the way that one is passed to qsort.

--
pete
Nov 14 '05 #3
pete wrote:

Pushkar Pradhan wrote:

But since I access the buffer
and try to assign its elements to another


To do just that one thing,
first, calculate the total number of bytes,
and then #include <string.h>, and use memcpy() or memmove().

--
pete
Nov 14 '05 #4
On Sat, 13 Dec 2003 21:24:16 -0600 Pushkar Pradhan <pu*****@gri.msstate.edu> wrote:
| I have some functions which take as i/p a buffer (it can be float, char,
| or 16 bit, int etc.). The result is another o/p buffer, its type is also
| flexible (it could be a float, char etc.).
|
| I try to pass both as "void *buf" so that it can accept any data type.
| But since I access the buffer and try to assign its elements to another
| I get compile errors (I have pasted at the end).
|
| Now my question is how can I pass the i/p and o/p buffers as args to the
| function without hardcoding the data type, someone earlier suggested to
| pass another argument which tells the type, e.g.
| myfunction(void * buf, 1, ...) 1 may indicate that buf is char type, 2
| means 16 bit etc.

Passing them as (void*) should be OK. The problem is in _using_ them as
(void*). You need to first cast the pointer to the desired type, or assign
the pointer to a variable defined to have that type. If you are interpreting
the data as if it were the byte/bit pattern for (double) in your machine's
(double) format, then cast your pointer to (double*) and dereference. Note
that some machines will require the alignment be correct and will warn even
if the alignment really is correct since it might not know what the run time
really would done. And if it might not be correct, your program could fail.
In that case you might have to memcpy() the data from the buffer to a variable
of the correct type. Or you can use a union of mixed types.

But even if you want to merely copy the data raw without interpreting it,
you are really still "interpreting" it as characters (in order to step
through each one by one to do the copy). So you'll need to cast to (char*)
to do that, or call memcpy() which does it for you (it's arguments are
(void*) but it treats them as (char*) internally).
| But that means having if .. else's inside the function to do the same
| thing. Is there any other way?
| Maybe this is not possible in C.

Possible and I have done it many times.

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 14 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: isxyos | last post by:
Hello, It's just a warning, but can anybody explain to me what this warning is: warning C4047: '=' : 'unsigned int ' differs in levels of indirection from 'void *' #include <stdio.h> void...
16
by: David Ford | last post by:
I have a macro that I use across the board for freeing ram. I'd like to clean up my code so I don't get these warnings. #define sfree(x) _internal_sfree((void **)&x) #define _internal_sfree(x)...
12
by: Daniel Sjöblom | last post by:
When I compile this (with GCC and optimizations on): void foo(void) { int a; float f = *((float *) &a); } I get the warning : "dereferencing type-punned pointer will break strict-aliasing...
29
by: junky_fellow | last post by:
Consider the following piece of code: struct junk { int i_val; int i_val1; char c_val; }; int main(void) {
28
by: Martin Jørgensen | last post by:
Hi, I have a "funny" question, which I think is pretty "healthy" to examine... This program is being investigated: - - - - - - - #include <iostream> using namespace std; #define DAYS 7
16
by: cody | last post by:
Shouldn't if (this!=null) generate a compiler warning? in fact, it does not.
4
by: Pritam | last post by:
line 7: error: dereferencing pointer to incomplete type 1. #include<stdio.h> 2. #include<sys/stat.h> 3. #include<stdlib.h> 4. void execname() { 5. struct task_struct *my; 6. my =...
28
by: Dave Stafford | last post by:
I have a macro that I use across the board for freeing ram. I'd like to clean up my code so I don't get these warnings. #define sfree(x) _internal_sfree((void **)&x) #define _internal_sfree(x)...
92
by: Heinrich Pumpernickel | last post by:
what does this warning mean ? #include <stdio.h> int main() { long l = 100; printf("l is %li\n", l * 10L);
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.