Confusion regarding a function definition in C - c

I found this function definition
void *func(void *param) {
}
Actually, I have a certain confusion regarding this function definition. What does void * mean in the return type of the function as well as the argument. I am a beginner in C. So please don't mind. Thank you
void *func(void *param) {
int s = (int)param;
....
}
Well looking at the above program which I found. I think it should have been
int *s = (int *)param;
isn't it? I am confused

void * means it's a pointer of no specific type, think of it as a generic pointer, unlike say int * an int pointer.
You can cast it into a different type if need be (for instance if you are going to do pointer arithmetic with the pointer).
You might find this SO question of use: Concept of void pointer in C programming

It simply means that the function func takes one parameter which is a pointer (to anything) and returns a pointer (to anything). When you use a void *, you are telling the compiler "this is a pointer, but it doesn't matter at this point what it's a pointer to".
When you want to actually use the data it's pointing to, you need to cast it to a pointer to some other type. For example, if it points to an int, you can create an int * variable and dereference that:
int *int_ptr = (int *)param;
// now (*int_ptr) is the value param is pointing to

you can think of it as a raw pointer, nothing more than an address, think about it, pointers are nothing more than address right, so they should all be of equal size, either 32 or 64 bits in most modern systems but if thats the case why do we say int * or char * or so on if they are all the same size, well thats because we need of a way to interpret the type we are pointing to, int * means when we dereference go to that address and interpret the 4 bytes as an int or char * means when we dereference go to that address and get a byte, so what happens when you dereference a void * well you get warning: dereferencing ‘void *’ pointer basically we really can't and if you do its affects are compiler dependent, the same applies when we do arithmetics on it.
So why bother using them? well I personally don't and some groups dont particularly like them, fundamentally they allow you to create fairly generic subroutines, a good example would be memset which sets a block of memory to a certain byte value, its first argument is a void * so it won't complain whether giving a char * or int * due note that it works on a per byte basis, and you need to properly calculate the total size of the array.

void *func(void *param) {
}
param is a void pointer means it is a pointer of any reference type. since a void pointer has no object type,it cannot be dereferenced unless it is case.
so void *param;
int *s=(int*)param;
here since param is an pointer variable so you will have to cast it as a pointer variable.not to a int type as you did there.
e.g.
int x;
float r;
void *p=&x;
int main()
{
*(int *)p=2;
p=&r;
*(float*)p=1.1;
}
in this example p is a void pointer. now in main method I have cast the p as a int pointer and then as a float pointer so that it can reference to first a integer and then a float.

Returning a pointer of any type. It can be of any datatype.

Related

Void pointers in c

I wrote these lines of code expecting them to work just fine but I keep getting an error that says "invalid use of void expression" and I have no clue why
int main(){
int a=12;
void* ptr = &a;
printf("%d",*ptr);
}
I thought void pointers can point to any type of data so what's the issue here? I even tried to cast the void pointer to an integer pointer but I still get the same error.
I thought void pointers can point to any type of data so what's the issue here.
A void * can point to any type of data1. But it only remembers the address, not the type. To use it with *, you must tell the compiler what type to use:
int a = 12;
void *ptr = &a;
printf("%d\n", * (int *) ptr); // Use cast to specify type.
During execution, the program will not remember that ptr was assigned an address from an int and automatically know to load an int in the printf call. During compilation, the compiler will not remember this either. To use the pointer to access data, you must convert it back to an appropriate type, then use that.
Footnote
1 A pointer should retain all the qualifiers of any object it is set to point to. A pointer to a const int x or volatile int x ought to be assigned to a const void *p or a volatile void *p, respectively, not a void *p without the qualifiers.
You can not dereference a void pointer, the underlying type (void) is incomplete.
You should either use a different type for your pointer (such as int*) or you should cast your void pointer to a complete type (again, probably int*).
You can't dereference a void*, as you've seen, but casting it to an int* most definitely works:
printf("%d",*(int*)ptr);
OnlineGDB demo

How to traverse an array parameter as void pointer

I have similar "generic" procedure like qsort, which has a void pointer (pointing at an array) and also a function pointer parameter. This function should work on any type of array.
Example:
void do_something(void * array, int count, int size, void (*test)(const void*)){
int i;
for(i=0; i<count; i++){
test(array + (index * size));
}
}
This however gives me the following warning (gcc test.c -pedantic-errors):
error: pointer of type ‘void *’ used in arithmetic [-Wpedantic]
And after some research I found out it's a bad practice to use void pointers like this. (E.g. Pointer arithmetic for void pointer in C)
So how does the standard library do this kind of stuff for like qsort? Looking at this code: (http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c), I see the following:
void
_quicksort (void *const pbase, size_t total_elems, size_t size,
__compar_fn_t cmp)
{
register char *base_ptr = (char *) pbase;
....
char *lo = base_ptr;
char *hi = &lo[size * (total_elems - 1)];
...
}
Are they casting to (char *) regardless of the actual type?
i asked similar question Can I do arithmetic on void * pointers in C?.
Void * arithmetic is not defined. What does it mean to add 1 to a void pointer ? Most compilers (if they allow it) treat it as incrementing by sizeof(char) ("the next byte") but warn you.
So the right thing to do is to explicitly make it do what you want -> cast to char* and increment that
Pointer arithmetic on incomplete data type void is not legal and that is what the compiler is complaining.
As you can see in the _quicksort() the pointer is a constant one so that you can't modify the address the pointer is pointing to. There is no arthmetic operation happening on the void pointer.
Making a pointer void just takes away the "context" of the pointer - That is, how the system should look at the pointer or whatever the pointer is holding.
For this reason, compilers do not do arithmetic on void pointers. In order to do pointer arithmetic, the compiler needs to know the type of the pointer such that it can do the proper conversions (if the pointer holds an int, it will not do an addition of with 32 bits or at least it will let you know something is gone awry!).
For this reason, the only way to do this is to cast the pointer to something and do it - I would not recommend it unless you know very well what the pointer is getting. Void pointers are rather very dark programming.

What exactly does void * mean

I have seen void * explained as a pointer to an unused chunk of memory. I have also seen void * described as a pointer to any type, or a pointer to any type can be cast to void *.
From what I know, int * means a pointer to type int. So keeping this in mind, what does void * mean literally? Is it a pointer to type void? This doesn't seem right because I did not know that void could be a type.
void * is a pointer to void.
C11: 6.3.2.3 Pointers:
A pointer to void may be converted to or from a pointer to any object type. A pointer to
any object type may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer.
The compiler will not let you dereference a void* pointer because it does not know the size of the object pointed to but you need to cast void * type pointer to the right type before you dereference it.
Let's begin with this example:
int a = 65;
int *q = &a;
void *p = q;
char *c = p;
(source: qiniudn.com)
we define an int variable a, and an int pointer q pointing to it. p in the void * pointer.
The beginning address of a is 0x8400(just for simplicity).
A pointer is an address, no more.
No matter what type of pointer, they have the same memory size, and their value is an address.
So,
printf("%p, %p", *p, *q);
will display:
0x8400, 0x8400
Type: how you interpret the date
As you see in the graph, the data in memory is 65000000(this is little endian). If we want to use it, we have to specify what it is! And type does that.
printf("%d %c", *p, *q);
If we print it as integer, we get 65. If we print them as char, we get A(asciicode).
And p + 1 pointer to 0x8401, q + 1 points to 0x8404.
void *: a universal type
According to wikipedia:
A program can probably convert a pointer to any type of data (except a function pointer) to a pointer to void and back to the original type without losing information, which makes these pointers useful for polymorphic functions.
Yes, void * define a trivial unit of pointer, it can be converted to any pointer and vise versa. But you can't dereference it, because it doesn't specify a type.
If you want to manipulator on bytes, you should always use void *.
Isn't char * the same as void *
Not exactly.
The C language standard does not explicitly guarantee that the different pointer types have the same size.
You can't always hope char * have the same size on different platforms.
And converting char * to int * can be confusing, and mistakes can be made.
It means: a pointer to some memory, but this pointer does not contain any information about the type of data that may be stored in that memory.
This is why it's not possible to dereference a void *: the operation of dereferencing (and obtaining an rvalue, or writing through an lvalue) requires that the bits in the memory location be interpreted as a particular type, but we don't know which type to interpret the memory as.
The onus is on the programmer to make sure that data read in matches the type of data read out. The programmer might help himself in this by converting the void * to a pointer to an object type.
It's useful if you want to have a common interface for dealing with memory of multiple possible types, without requiring the user to do a lot of casting. for example free() takes a void * because the type information isn't necessary when doing the free operation.
void * is a pointer to data of unspecified type. As such, it can't be used directly; it must be cast to a usable datatype before it can be dereferenced.

Why type cast a void pointer?

Being new to C, the only practical usage I have gotten out of void pointers is for versatile functions that may store different data types in a given pointer. Therefore I did not type-cast my pointer when doing memory allocation.
I have seen some code examples that sometimes use void pointers, but they get type-cast. Why is this useful? Why not directly create desired type of pointer instead of a void?
There are two reasons for casting a void pointer to another type in C.
If you want to access something being pointed to by the pointer ( *(int*)p = 42 )
If you are actually writing code in the common subset of C and C++, rather than "real" C. See also Do I cast the result of malloc?
The reason for 1 should be obvious. Number two is because C++ disallows the implicit conversion from void* to other types, while C allows it.
You need to cast void pointers to something else if you want to dereference them, for instance you get a void pointer as a function parameter and you know for sure this is an integer:
void some_function(void * some_param) {
int some_value = *some_param; /* won't work, you can't dereference a void pointer */
}
void some_function(void * some_param) {
int some_value = *((int *) some_param); /* ok */
}

Pointer mismatch for actual parameter?

I have a function which creates an array of pointers. The function which allocates the memory returns the new memory pointer through a parameter passed to the function. The simplest code which can reproduce the problem is as follows:
void foo (void** new_mem, size_t bytes)
{
*new_mem = malloc(bytes);
}
int main (void)
{
int** ptr_arr; // Want to create an array of pointers
foo(&ptr_arr, sizeof(int*)*100); // Create an array size of 100
// compiler emits warning:
// 'void **' differs in levels of indirection from 'int ***'
return 0;
}
I could cast the first parameter passed to foo like so: '(void**)&ptr_arr' to get rid of the warning, however, I'm wondering: Is there a more appropriate solution?
Although there's a guaranteed conversion from int * to void *, there's no such guarantee for converting from int ** to void **. To think about why this might be, consider that an int * might actually be smaller than a void *. As a result, using a void ** pointer to walk over an array of int *s will walk the wrong stride and get the wrong data. Furthermore, there's no guarantee that int * will use the same representation as void *, only that there is a way to convert between them.
In practice, I don't know of any machines where this will fail. But it's not guaranteed by the standard.
EDIT: eek, and what everyone says about passing an int ***. But even if you pass an int **, the above still applies.
EDIT2: the comp.lang.c FAQ has an excellent discussion about this.
The problem is you're taking the address of a double pointer and passing it to a double pointer parameter. Taking the address of a value creates a pointer so you end up really with a triple pointer int*** which is why you get the error.
Casting the result to void** will technically work here although it is bordering on an abuse on the type system.
The trouble is ptr_arr is already an int **,
when you do an &ptr_arr, it will show as int *** , so what you are doing is incorrect.
So, you can just pass ptr_arr if your intention is to pass an int **
Also, I feel your code can do well with a cleanup. Your approach seems to be wrong.

Resources