Generic pointer to pointer - c

I understand that according to standard void * is generic pointer, and void ** is not. So, in my program, I am trying to cast void * and not directly type cast void ** but I am not getting expected results. I think I am missing something very basic in here.
#include <stdio.h>
void check(void **p)
{
printf("value: %d\n", *(int *)*p);
}
int main()
{
int a[] = {6,2,5,1,8};
int *p;
p = a;
void **val;
val = (void *)p;
check(val);
return 0;
}
I have a void ** pointer val, which is pointing to int * but casted to void *. I pass this to function check, which is expecting void **. In my printf, I first cast *p (which is void *) to int * and then derefernce it. I get some random value. Am I missing something here?

The problem is in the call to printf:
printf("value: %d\n", *(int *)*p);
In main, val (which is a void **) contains the contents of a int *. This is then passed to check, where is now called p. This needs to be casted to an int * to read correctly:
printf("value: %d\n", *(int *)p);
Of course, since a void ** is not a generic pointer, it doesn't make much sense to do this. Best to get rid of the extra level of indirection which isn't being used anyway:
void check(void *p)
{
printf("value: %d\n", *(int *)p);
}
int main()
{
int a[] = {6,2,5,1,8};
int *p;
p = a;
void *val;
val = p;
check(val);
return 0;
}

Change val = &p; to val = p;
Probably it was a kind of "typo" since you had already passed the value once correctly and later also dereferenced it.
EDIT:
You can change: val = (void *)p; to val = (void *)&p;

As you said yourself, void** is not a generic pointer. It is a pointer that point to an object of type void*, and nothing else. Using a cast to point it at an object of type int* is type punning.
In your case, you should simply cast your int* to void*, and back to int* again. No void** involved.

Related

Returning a value from a thread in C

Hello i am having a hard time understanding how a value is returned from a thread in c. I have this working example:
#define NTHREADS 4
void *neg (void * param) {
int *l;
l=(int *) param;
int *r=(int *)malloc(sizeof(int));
*r=-*l;
return ((void *) r);
}
int main (int argc, char *argv[]) {
pthread_t threads[NTHREADS];
int arg[NTHREADS];
int err;
for(long i=0;i<NTHREADS;i++) {
arg[i]=i;
err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i]));
if(err!=0)
error(err,"pthread_create");
}
for(int i=0;i<NTHREADS;i++) {
int *r;
err=pthread_join(threads[i],(void **)&r);
printf("Resultat[%d]=%d\n",i,*r);
free(r);
if(err!=0)
error(err,"pthread_join");
}
return(EXIT_SUCCESS);
}
What i find hard to understand is the following:
the function neg returns a pointer * r casted in (void *) pointing to a value in the heap. Thus returning an adress to the heap basically. Then in pthread_join we get that return value by doing &r (which by itself seems illogical? grab the adress of an adress?) then casting to a pointer of a pointer? Why do we do that?
Thanks for the help!
Consider this code, which is perfectly valid and prints "5 5 5 5".
int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
printf("%d %d %d %d\n", x, *p, **pp, ***ppp);
return 0;
C allows you to have any depth of pointers, initialized with a corresponding number of address-of operators. In your example, you allocated an int * and the function must return a void **, so you have to dereference the result twice and cast it, which you accomplished by casting the int *.
So,"grab the adress of an adress?" Yup! Well, the address of a pointer, which may hold the address of an int, or another pointer.
Then in pthread_join we get that return value by doing &r (which by
itself seems illogical? grab the adress of an adress?) then casting to
a pointer of a pointer? Why do we do that?
First thing you need to understand is that the thread function(s) do not return the value directly; they send the value to the pthreads library using pthread_exit() or returning a value (as in your example) and
it's retrieved with a call to pthread_join() (by using the thread identifier). Since the return value is a pointer, you have to
pass a pointer to pointer to retrieve it from pthread_join() function.
For the understanding purposes, consider this pseudo code:
/* thread */
void *neg(void *arg)
{
return ptr; // let's say "ptr" is stored in the library as "retval_thread_id"
}
int pthread_joing(pthread_t thread_id, void **retval)
{
*retval = retval_thread_id;
}
int main(void)
{
rc = pthread_join(threads[i],(void **)&r);
}
So, how can you retrieve the pointer retval_thread_id from pthread_join() without using a pointer to pointer?
This is nothing different than passing a ptr-to-ptr to a function and the function stores at the pointee of the passed pointer:
void func(int **p)
{
*p = malloc(10 * sizeof *p);
}
int main(void)
{
int *p;
func(&p);
}
By the way , all the casts you do (except the one in the call to pthread_join() -- You wouldn't this either if you declared r as void *r;.) are unnecessary. A void pointer can be assigned to any other data pointer in C without a cast.

Swapping 2 string pointers with a function whose parameters are void **

The following code doesn't compile:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap(&s[0], &s[1]);
return 0;
}
While this code compiles and runs just fine:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap((void **) &s[0], (void **) &s[1]);
return 0;
}
Why is the casting necessary ?
Yeah, so in addition to the already existing answers that point out that void ** is not the same as char **: your code invokes undefined behavior because of the incompatible pointer types. Here's what you actually want:
void swap(void *p1, void *p2, size_t size)
{
unsigned char buf[size];
memcpy(buf, p1, size);
memcpy(p1, p2, size);
memcpy(p2, buf, size);
}
And call it like this:
const char *s[] = { "help", "please" }; // also note the use of `const' for string literals
swap(&s[0], &s[1], sizeof(s[0]));
You have incompatible pointer assignment error in first code. In C type of a string literal is char[N] Where N is number of chars. Note in most of expressions char[N] easily decays into char*
According to your declaration char *s[] = {"help" , "please"}; type of s[i] is char* (actaully char[N] decayed into char*).
When you pass &s[i] then you are passing char** that is incompatible with void**. Second code works because you typecast into void** in function calling.
void* can be assigned any address type but its void** that has to be assigned address of void* type variable.
If you only having array of strings then in first version of swap function you can replace void by char then you can all without typecast.
The casting makes the example compile because of what you are passing the function.
char *var[]; is in many ways the same as char **var;
With that being said, you are passing the function a reference/address one of the members of the array (s[0]).
Another more prominent issue, is that the function accepts void pointers, and is passed character pointers (without the casting).

Posix Pthread in C

I have the following questions regarding pthread of posix.
When we receive data in pthread_join() returned by the function being executed by a thread, we type cast the variable like (void **) even though the variable is a single pointer.
int *x;
pthread_join(tid,(void**)&x);
printf("%d",*x);
Should I derefrence the type casted argument (in case of structure)? Why can't I do like
struct Data *obj= & (struct Data*)arg;?
int main()
{
...
pthread_create(tid,NULL,Foo,&obj);
...
}
void *Foo(void *arg)
{
struct Data *obj=* (struct Data*)arg;
}
How does pthread_join() internally receives the returned variable.
Regards
First of, you should never do (void**)&x as pointers off different types need not be of the same size.
Now, some scenarios (some valid, some working but invalid and some just broken):
Foo() returning a pointer to an int (valid):
void* Foo(void *arg)
{
int *ret = malloc(sizeof(int));
*ret = 42;
return ret;
}
void *ptr;
int *x;
pthread_join(thread, &ptr);
x = ptr;
printf("%d", *x);
free(x);
Foo() returning an int (invalid but usually work):
Platforms where int is larger than a pointer this will not work.
void* Foo(void *arg)
{
return 42;
}
void *ptr;
int x;
pthread_join(thread, &ptr);
printf("%d", (int)ptr);
Foo() returning a pointer to static int (invalid and never works):
All static memory in Foo() is freed when Foo() returns, before pthread_join() can copy the value.
void* Foo(void *arg)
{
int ret = 42;
return &ret;
}
void *ptr;
int *x;
pthread_join(thread, &ptr);
x = ptr;
printf("%d", *x);
You shouldn't do that: at your level of understanding of C casts should be simply forbidden.
If you learned that in a course, this is not really high quality.
First of all, &x is the address of a pointer so the result is int**, so well two indirections.
But casting that int away is dangerous, pointers to int and void don't have necessarily the same width on different platforms. So please do
void*x;
pthread_join(tid, &x);
printf("%d",*(int*)x);

Can I get a pointer to a struct as a parameter from a function in C?

I have a type defined like this:
struct DynTab_s {
int object_count;
//other fields
void *data;
};
typedef struct DynTab_s *Dyntab_t; //note that type I use is pointer to struct
I have a storage utility that I can user to store and retrieve them. I've chosen to support int, double and pointer type. I have a function to retrieve the int and double values by key:
int MyHashtableGet(MyHashtable_t Hashtable, void *Key, void *Value)
{
void *Row = NULL;
int RetValue = -1;
MakeRow(Hashtable, Key, NULL, &Row);
if (!MyStoreSelect(Hashtable->TableId, Row))
{
switch (Hashtable->ValueType)
{
case MY_HASHTABLE_TYPE_INT:
*(int *)Value = *(int *)((char *)Row + Hashtable->KeySize);
break;
case MY_HASHTABLE_TYPE_POINTER:
//after row below I can see the DynTab_t in the item when I cast it
Value = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
break;
}
}
MyFree(Row);
return RetValue;
}
that work for int. But not for pointer when I try to get Dyntab_t. This works if I use function
void *MyHashtableGetPointer(MyHashtable_t Hashtable, void *Key)
{
void *Row = NULL;
void *RetValue = NULL;
MakeRow(Hashtable, Key, NULL, &Row);
if (!MyStoreSelect(Hashtable->TableId, Row))
RetValue = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
MyFree(Row);
return RetValue;
}
when I call it with:
int Key = 1;
DynTab_t MyTab;
MyTab = (DynTab_t)MyHashtableGetPointer(MyHashtable, &Key);
The question is can I at all use this MyHashtableGet to get DynTab_t item or does second parameter have to be void ** type? If yes, can you please provide the exact syntax to call and to MyHashtableGet in case of MY_HASHTABLE_TYPE_POINTER.
Thanks & BR -Matti
The question is can I at all use this MyHashtableGet to get DynTab_t item or does second parameter have to be void ** type?
The only difference (if you're storing the pointers like you store the int values) would be that when retrieving an int, you'd pass the address of an int variable; and when retrieving a pointer, you'd pass the address of a pointer variable. A void * can hold the address of anything (except functions sometimes) -- including other pointers. So the last parameter is fine as void *, as long as you handle it appropriately elsewhere.
I'm not sure what you're doing in your function, though. If you store the pointers the same way as the ints in your data structure, so that at the same level of indirection you'd have an int for the integer type and a void * for the pointer type, then why are they dereferenced to different levels?
case MY_HASHTABLE_TYPE_INT:
*(int *)Value = *(int *)((char *)Row + Hashtable->KeySize);
break;
In the above, it seems that ((char *)Row + Hashtable->KeySize) gets you the pointer to whatever value you've stored, though of the wrong pointer type. Then the (int *) casts to a pointer of your data's type (int in this case), which you then dereference and assign to what Value points to.
case MY_HASHTABLE_TYPE_POINTER:
Value = *(void **)*(int **)((char *)Row + Hashtable->KeySize);
break;
But here, you cast to int **, dereference, cast to void **, then dereference again, and assign to Value instead of what Value points at? Isn't that one too many dereferences? Shouldn't you assign to the target of Value rather than Value? And why do you need to cast to int ** at all? I think it should be more like this:
case MY_HASHTABLE_TYPE_POINTER:
*(void **)Value = *(void **)((char *)Row + Hashtable->KeySize);
break;
Then, when calling to get an int:
...
int Val;
MyHashtableGet(Table, Key, &Val);
...and when calling to get a pointer:
...
void *Val;
MyHashtableGet(Table, Key, &Val);
Edit:
This assumes one of two things, though: That the the variable you passed the address of in Value is void *, or that the variable you passed the address of is of a type that is internally represented the same way as void * (often true, but not guaranteed). If you want to rely on the pointer type being converted on assignment (in case their representations differ), you could implement your MyHashtableGetPointer() function as a wrapper for MyHashtableGet():
void *MyHashtableGetPointer(MyHashtable_t Hashtable, void *Key)
{
void *res = NULL;
MyHashtableGet(Hashtable, Key, &res);
return res;
}
It really depends on how you want to do it. You can do it using a reference (only in C++) or a pointer (C and C++):
void changeTheParamRef(struct myStruct &s)
{
myStruct other;
s = other; // or
s.something = other.something;
}
void changeTheParamPtr(struct myStruct *s)
{
myStruct other;
*s = other; // or
s->something = other.something;
}
void allocStruct(struct myStruct **s)
{
*s = malloc(sizeof(myStruct));
}
You don't need a pointer to a pointer unless you'd like to return or change a pointer instead of a value.
To call above samples:
myStruct s;
changeTheParamRef(s);
changeTheParamPtr(&s);
myStruct *p;
allocStruct(&p);
changeTheParamRef(*p);
changeTheParamPtr(p);

dynamic memory created inside a function [duplicate]

This question already has answers here:
C Programming: malloc() inside another function
(9 answers)
Closed 5 years ago.
I would like to know the technical reason(in terms of memory) why this piece of code will not work:
#include <stdio.h>
#include <stdlib.h>
int* fun(int*);
int main()
{
int a=5;
int* ptr;
// ptr=(int*)malloc(sizeof(int));
fun(ptr);
a=*ptr;
printf("\n the val of a is:%d",a);
return 0;
}
void fun(int* ptr)
{
ptr = (int*)malloc(sizeof(int));
*ptr = 115;
}
Why will this not work? I thought that the heap(more importantly the addresses) is common to all the function's variables in the stack .
Also, why would this work.
If i comment the memory allocation inside the function fun and uncomment the one in main . It works fine.
In C, everything is passed by value.
What you are passing to fun() is a copy of the pointer you have in main().
That means the copy of ptr is aimed at the allocated memory, and that memory set to 115.
The ptr in main() still points at an undefined location because it has never been assigned.
Try passing a pointer to the pointer, so that within fun() you have access to the pointer itself:
#include <stdio.h>
#include <stdlib.h>
int* fun(int**); // <<-- CHANGE
int main()
{
int a=5;
int* ptr;
// ptr=(int*)malloc(sizeof(int));
fun(&ptr); // <<-- CHANGE
a=*ptr;
printf("\n the val of a is:%d",a);
return 0;
}
int* fun(int** another_ptr) // <<-- CHANGE
{
*another_ptr = (int*)malloc(sizeof(int)); // <<-- CHANGE
**another_ptr = 115; // <<-- CHANGE
return *another_ptr;
}
The other option would be to make fun() actually return the updated pointer (as advertised), and assign this to ptr:
#include <stdio.h>
#include <stdlib.h>
int* fun(int*);
int main()
{
int a=5;
int* ptr;
// ptr=(int*)malloc(sizeof(int));
ptr = fun(ptr); // <<-- CHANGE
a=*ptr;
printf("\n the val of a is:%d",a);
return 0;
}
int* fun(int* another_ptr)
{
another_ptr = (int*)malloc(sizeof(int));
*another_ptr = 115;
return another_ptr; // <<-- CHANGE
}
Edit: I renamed the variable in fun() to make it clear that it is different from the one you use in main(). Same name doesn't mean anything here.
The fun() function parameter is a copy of the variable you passed into fun(). So when you do:
ptr = (int*)malloc(sizeof(int));
*ptr = 115;
you only change that copy. You should change the function signature:
int* fun(int** ptr)
{
*ptr = (int*)malloc(sizeof(int));
**ptr = 115;
}
and change how you call it accordingly.
You are confused about several things here, but one easy way of writing the function is:
int * fun()
{
int * ptr = (int*)malloc(sizeof(int));
* ptr = 115;
return ptr;
}
You are now responsible for freeing the memory, so in main():
int * ip = fun();
printf( "%d", * ip );
free( ip );
The alternative is to pass the address of apointer (a pointer to a pointer) to the function:
void fun( int ** pp )
{
* pp = (int*)malloc(sizeof(int));
** pp = 115;
}
then your code in main() looks like:
int * ip;
fun( & ip );
printf( "%d", * ip );
free( ip );
I think you can see that the first function is simpler to use.
You need to pass the address of the pointer in main if you want to change it:
fun(&ptr);
(and change fun appropriately, of course)
At the moment, it's changing the local variable ptr inside the function, and of course that change doesn't magically appear anywhere else.
You're passing the ptr by value to fun. fun will recieve a copy of ptr which will be modified. You need to pass ptr as int**.
void fun(int** ptr)
{
*ptr = (int*)malloc(sizeof(int));
**ptr = 115;
}
and call it with:
fun(&ptr);
(I also removed the return value from fun since it wasn't used)
The variable int* ptr is passed by value to the function fun. So the value assigned to ptr inside the function using ptr = (int*)malloc(sizeof(int)); will not be reflected outside the function. So when you do a = *ptr; in main() you are trying to use an un-initialized pointer. If you want to to reflect the changes done to ptr outside the function then you need to change the signature of fun to fun(int** ptr) and do *ptr = (int*)malloc(sizeof(int));
Remember that if you want a function to modify the value of an argument, you must pass a pointer to that argument. This applies to pointer values; if you want a function to modify a pointer value (not what the pointer points to), you must pass a pointer to that pointer:
void fun (int **ptr)
{
/**
* Do not cast the result of malloc() unless you are
* working with a *very* old compiler (pre-C89).
* Doing so will supress a valuable warning if you
* forget to include stdlib.h or otherwise don't have
* a prototype for malloc in scope.
*
* Also, use the sizeof operator on the item you're
* allocating, rather than a type expression; if you
* change the base type of ptr (say from int to long),
* then you don't have to change all the corresponding
* malloc() calls as well.
*
* type of ptr = int **
* type of *ptr = int *
* type of **ptr = int
*/
*ptr = malloc(sizeof **ptr);
*ptr = 115;
}
int main(void)
{
int *p;
fun(&p);
printf("Integer value stored at %p is %d\n", (void *) p, *p);
return 0;
}
BTW, you have a type mismatch in your example; your initial declaration of fun returns an int *, but the definition returns void.

Resources