I'm trying to learn on C multithreading, and I've seen a couple of rare things.
I understand that passing parameters to a thread must be done with pointers. I've found an example which I don't understand. I'll copy the relevant lines:
pthread_t tid[MAX_THREADS]
int n_veg
pthread_create(&tid[n],NULL,caracter,(void *)n_veg)
caracter is obviously a predeclared function.
Now, why do we use a void pointer casting instead of a int pointer casting? Is there any relevant difference?
Secondly, why do we use a pointer casting in the first place? Can't we use "&n_veg" like with the first parameter?
Thanks in advance.
Since both your questions are related, I'll answer them together: pthread_create takes a void * parameter, so you can really pass in any pointer you want. In this case though, we aren't actually passing a pointer, but just a simple integer value casted as a pointer. That means you will access it like this in caracter:
int value = (int)n_veg;
As you mentioned, you could very well pass an actual pointer as &n_veg and retrieve the value like this:
int value = *(int *)n_veg;
In fact, in most cases, you will need to pass more data than just an integer, such as a structure, and in that case, you must pass a pointer, as you can't simply cast it to a pointer like an integer.
One thing to keep in mind when you pass a pointer is that n_veg must not go out of scope as long as the thread is running. For example, if you do:
void test() {
int n_veg;
pthread_create(&tid[n],NULL,caracter,&n_veg);
}
then &n_veg will be invalid as soon as test returns, but the thread may still be running and will be holding an invalid address. Because of this, structures passed to threads are normally dynamically allocated, say using malloc, and the thread can free it once it has completed.
pthread_create is defined as follows:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void *), void *restrict arg);
So it expects a void * as its last parameter. If you omit the cast, the compiler would give you a warning.
Related
I am learning C language and doing a lot of practice. I understand that * and ** are pointers in .c function.
Please consider the following function (another .c function)
void pcc(int* n, int* d, int* family, int* type, double* par, double* nu, double* out)
{
int i, j, in=1, k, **fam;
double *w, **v, t, **theta, **x, **ny;
…some works
}
My question is, why do we use the pointer in the argument of the function? Because as I understand we use the pointer to point the previous identifed elements.
Also, why do we use pointer for some elements that are not already defined in the arguments of the function. For example, in the last function we define a new element after writing the argument of the function:
int i, j, in=1, k, **fam;
double *w, **v, t, **theta, **x, **ny;
For instance, double *w was not in the argument of the function! also **v and other elements. How do we know they must get ** or *.
Any help please?
The reasons for declaring a variable a * or ** are countless, it's better to try and get a grip of what they actually mean instead of getting hung up on why they're used in this specific instance.
A pointer * is a reference to a memory location where a value is stored. In the case of a char it is a reference to a single memorylocation holding a byte, and in the case of an int it's usually 4 bytes on a 32bit system.
You can pass a pointer as an argument to indicate this is where you want the result to be stored. Another reason might be efficiency. If you have a very large struct it's better to pass a 4byte (on a 32bit system) reference to the area of memory where the struct lies instead of loading the entire struct on the stack.
A ** is a double pointer. It is pointing to a specific memory location that itself is storing the memory location of something else.
char a[5];
Here, the variable a is actually a char * pointing at the first element of a[], namely a[0].
char a[5][5];
Here a is a char **, pointing to the first element of a[][], namely a[0], which will return a char * pointing at a[0][0].
The second example is better when you want to fiddle with the pointers. Maybe you have a char** (an 'Array of strings'), and you want to replace one of the 'strings' (a string is just a char[] in c), you simply change the char* pointed to by the char**).
I hope this makes it a little clearer for you.
Pointers are used when we want the location of a value, as opposed to just the value. Now why would we want this? One simple scenario is actually illustrated in your question. In c, it is often inconvenient (if not impossible) to return more than one value from a function. An easy way to get around that is with pointers! When you pass arguments into a function normally, for example
int myFunction(int some_parameter);
you are actually passing a copy of some_parameter into your function. When the function returns, the original value of some_parameter is unchanged. But what if we want to change some_parameter in the function? We pass a pointer to the value instead. This allows us to directly change the value of some_parameter at its original memory location, instead of a copy. So as you can see, if we instead had
void myFunction(int* parameter1, int* parameter2) {
*parameter1 = 1;
*parameter2 = 2;
}
When you exit the function, your values parameter1 and parameter 2 will be 1 and 2 respectively, even though you never actually returned a value!
Pointers are one of the most useful and difficult parts about c, and I recommend you consult the other sources that others have selected in order to learn more about them.
In C you traditionally use pointers to modify variables that were declared at a different scope than the one of your function.
Pointers to pointers (**) though, are usually used when you want to manipulate those addresses in some way.
Now as for you question:
How do we know they must get ** or *?
Well it depends on what you want to do with the data. If you want to manipulate the value you only need a pointer; if you want to manipulate the address you may need a pointer to a pointer.
In the code below, what is the role of the int sid=*(int*)args construct?
void *thread_p(void *args)
{
int sid=*(int*)args,i,size=0;***This initialisation in the thread function means what?***
char msg[100];
while(1)
{
for(i=0;i<100;i++)
msg[i]='\0';
recv(sid,msg,100,0);
printf("\nClient:%s",msg);
printf("\nServer:");
gets(msg);
size=strlen(msg);
send(sid,msg,size,0);
if((strcmp(msg,"exit"))==0)
{
close(sid);
exit(1);
}
}
}
I'm going to make an assumption here that thread_p is a pthread_create start routine. Such a start routine is required to accept a void pointer, which in C and C++ means a pointer to an untyped block of memory. Now, in addition to a start routine, pthread_create also accepts a void pointer argument, which it passes to the start routine. It is up to the caller of pthread_create to coordinate the call to pthread_create with the code in the start routine. So if the start routine given to pthread_create assumes the void pointer points to, say, an integer, then the call to pthread_create must pass a pointer to an integer as the arg parameter to keep things in sync. This is a type-unsafe interface. The compiler won't help you make sure these are in sync, and if they are not, you'll get undefined behavior.
Your thread_p function is assuming that the arg passed to it actually points to an integer. It is first casting the void pointer to an integer pointer (that is the (int*)args part) and then dereferencing the pointer to get the integer that it points to (that's the * in front of the (int*)args). If the caller of pthread_create passed it thread_p, but failed to pass the address of an int as the arg parameter, the code would have undefined behavior.
In this below link
https://computing.llnl.gov/tutorials/pthreads/samples/hello.c
in the statement rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t); the coder has just passed a variable as 4th argument without passing address of that variable. Is this code correct? If yes how can we cast a variable to void *
The above link seems to be popular as it is listing first in Google for pthreads.
Well it is a bit weird, but it does what it is supposed to.
The fourth argument is sent as argument to the PrintHello function/routine. It has to be passed as a void *.
Typically you have a pointer to a dynamically allocated object that you cast to void *. But here he defines a long t, casts it to void * (address) and sends it in. Then he casts it back to a long in PrintHello, so all is fine, but a bit ugly and could have gone "horribly" wrong if he would have cast it to a pointer and tried to access the memory it pointed to.
Yes this code is correct, if you don't try to access the memory pointed to by the parameter in the thread. Just convert it to a long in the thread.
tid = (long)threadid;
It converts the pointer to a long, but it doesn't touch the memory space that the pointer points to, which is most likely junk and will cause access violations.
For example if you did:
tid = (long)*threadid;
That would cause an access violation because you are trying to access the memory at the location pointed to by threadid.
If you would rather pass the pointer to a long integer you could do something like this.
...
long* pint = (long*)malloc(sizeof(long));
*pint = t;
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)pint);
void *PrintHello(void *threadid)
{
long* tid;
tid = (long*)threadid;
printf("Hello World! It's me, thread #%ld!\n", *tid);
free(tid);
pthread_exit(NULL);
}
But that requires the use of malloc and free
Keep in mind that a pointer is nothing more than a 32 or 64bit unsigned integer which represents a location in memory, you can put any number you want in a pointer, just don't try to access the memory it points to.
Hope that helps,
-Dave
Actually the 4th argument is the parameter to be passed to the thread, for example if there is a value that needs to be passed from the main thread to the newly created one, then this is done through this 4th argument. For example:
Lets say I have a thread being created from the main loop:
Int32 l_threadid = pthread_create(&l_updatethread,NULL,Thread,&l_filter);
As you can note that I'm passing the address of a value that is going to be used in the thread being created in the following way:
void* Thread(void *p_parameter)
{
int *l_thread_filter = (int *)p_parameter;
.... then play around with this variable ...
}
consider the the two functions :
int add1(int x,int y)
{
return x+y;
}
void add2(int x,int y,int *sum)
{
*sum=x+y;
}
I generally use functions of the form add1 but I found some codes using functions of the form add2.
Even if the size return value is large(like an array or struct) we can just return its ponter
I wonder if there any reason for using the second form?
There's also the reason of returning success state.
There are a lot of functions like:
bool f(int arg1, int arg2, int *ret)
{
}
Where bool (or enum) return the success of the function. Instead of checking if ret is null... (And if you had more than 1 variable).
If you want to return two values from your function, then C is helpless unless you use pointers just like your function add2.
void add2()
{
/* Some Code */
*ptr1=Something;
*ptr2=Something;
}
Form 2 is very common for "multiple returns" in C. A canonical example is returning the address to a buffer and the length of the buffer:
/* Returns a buffer based on param. Returns -1 on failure, or 0 on success.
Buffer is returned in buf and buflen. */
int get_buffer(void *param, char **buf, int *buflen);
Functions of the form 2 are not faster than functions of the form 1 when you're using things as small as int. In fact, in this case, the second one is slower because you have to dereference the passed pointer. It's only useful in this case if your aim was to pass in an array of values)
Always use functions of the form 1 unless you want to pass in a very large piece of data to the function. In that case, the form 2 would be faster.
The reason we use the second form is because for large objects, we want to avoid copying them. Instead of copying them, we could just pass their memory addresses to the function. This is where the pointer comes in. So instead of giving the function all the data, you would just tell it where this data. (I hope this analogy is good enough)
It is largely a matter of preference and local conventions. The second form might be used alongside a bunch of other similar functions where the third parameter in each of them is always passed as a pointer to a return value.
Personally, I like the first form for almost all purposes: it does not require a pointer to be passed, and it allows some type flexibility in handling the return value.
Returning a value by writing to memory passed via a pointer is reasonable, when the returned object is large, or when the return value of the function is used for other purposes (e.g. signaling error conditions). In the code you have shown, neither of these two is the case, so I'd go for the first implementation.
When you return a pointer from a function, you have to make sure that the pointed to memory is valid after the function call. This means, the pointer must point to the heap, making an allocation on the heap necessary. This puts a burdon on the caller; he has to deallocate memory that he did not explicitly allocate.
i am trying to write an easier version of scanf. i want to basically be able for a pointer to be assigned whatever was scanned on user input like this:
int *p = (int) w_insc();
so here is my implementation:
void *w_insc()
{
void *temp = 0;
scanf("???", &temp);
return &temp;
}
i am confused as what to assign the format parameter in scanf to. i also think returning an address of a variable that will soon be destroyed is not right so i thought of doing this:
int *p = 0;
p = (int) w_insc((int) p);
can someone help
You are right that returning a pointer to a soon-to-be-destroyed variable is not correct. You can solve this problem by returning a pointer to a memory region allocated with malloc (although the caller must remember to free this memory), or by taking a pointer as the argument to w_insc, and then filling in the pointer with the returned value.
However, there are much broader issues with trying to implement the w_insc function. There is no way for w_insc to know what the caller expects. Just because the caller casts the return value of w_insc to int doesn't allow w_insc to know that it should return an int. The only information that a C function has available to it is its set of parameters, plus any global variables in the program (and global variables are usually the wrong way to solve your problem). Note that a C function has no way of knowing what the caller will do with its return value. As a result, there is no way to write w_insc to take no parameters and return something scanned correctly based on some cast that the caller makes.
You could add a parameter to w_insc, making the declaration into
int w_insc(const char *format, ...)
This allows the caller to pass in a format string and a series of arguments detailing what they expect to get out of standard input. However, with this implementation you have just wrapped scanf with ... another function that looks just like scanf.
My advice: use the standard library functions, since they are standardized, and someone reading your code will know instantly what it means, rather than having to read through the definition of a nearly-trivial wrapper like the w_insc you have described.