Add elements to fifo queue - c

I'm trying to add int variables to this fifo.
fifo.c
But I only see the same var (this is the last var)
fifo_t *ff = fifo_new();
for (int i =0; i<4; i++) {
int *k = malloc(sizeof(int));
*k = rand();
printf("%d %p!\n", *k, k);
fifo_add(ff, k);
free(k);
}
fifo_iter(ff, my_callback, NULL);
If I create int var in stack and add to fifo like this
int x =0;
fifo_add(ff, (void *)x);
x = 2;
fifo_add(ff, (void *)x);
x = 3;
fifo_add(ff, (void *)x);
It is work fine, but I have warning - "cast to pointer from integer of different size"
What I do wrong? Best regards.
EDIT:
I found function in fifo.c for destroying all elements of fifo queue. For my example, you need to call fifo_free(of, NULL); If you will add your custom struct to the queue, you need to will write some function for destroying you struct and put it in second parametr of fifo_free.
ty for #JonathanLeffler and other commentators

Use
fifo_add(ff, &x);
You need to pass a pointer to data, rather than a casted scalar type, because fn_data is declared to be a void *, and a void * is not guaranteed to hold all scalar types. As a result, it's not possible to add int variables to a fifo.
Also note that
int x =0;
fifo_add(ff, &x);
x = 2;
fifo_add(ff, &x);
x = 3;
fifo_add(ff, &x);
may not work as you expect. It's the address of x that is stored in the new node, not the value it contains. So you will end up getting 3 new nodes, whose fn_datas point to a common memory.

Related

How call by reference and call by value works on multidimensional pointer arrays?

Can anyone explain me why i dont need -> int ***zd in the init function? Isn't this call by value and the intialization shouldnt stay when i want to print it? Or is a pointer automatically call by reference?
I would love to understand how this exactly works, so if anyone can help me i would highly appreciate it!
#include <stdio.h>
#include <stdlib.h>
void initZD(int **zd, int width, int height){
for(int i = 0; i < width; i++){
for(int j = 0; j < height; j++){
zd[i][j] = rand() % 10;
}
}
return;
}
void printZD(int **zd, int breite, int hoehe){
for(int i = 0; i < breite; i++){
for(int j = 0; j < hoehe; j++){
printf("%d\t",zd[i][j]);
}
printf("\n");
}
}
int main(){
int **zd = NULL;
int width, heigth;
printf("Width: ");
scanf("%d", &width);
printf("Heigth: ");
scanf("%d", &heigth);
//zd = realloc(*zd, breite*sizeof(int));
//zd = calloc(breite, sizeof(int));
zd = malloc(width*sizeof(int));
for(int i = 0; i < width; i++){
//zd[i] = realloc(*zd, hoehe*sizeof(int));
//zd[i] = calloc(hoehe, sizeof(int));
zd[i] = malloc(heigth*sizeof(int));
}
initZD(zd, width, heigth);
printZD(zd, width, heigth);
free(zd);
for(int x = 0; x < width; x++){
free(zd[x]);
}
return 0;
}
initzD does not need the address of zd because it does not change zd. It changes things that are pointed to via zd (specifically things that are pointed to by pointers that zd points to).
To change those things, it needs their addresses, and it has their addresses because they are pointed to by the pointers that zd points to. (Generally, the pointers only point to the first of some number of int, but the subscript operators in zd[i][j] do pointer arithmetic to calculate the addresses of following elements.)
The parameter doesn't need to be defined as int ***zd because you're not modifying the value of the pointer zd in the main function. You're just dereferencing it to modify values that it points to.
Had zd been uninitialized, then you would have to pass a pointer to it so that the function could do the memory allocation that is currently happening in main.
Call by value would mean that a copy of a variable is passed to the function whereas Call by reference would mean that the address of the variable itself is passed.
The implication of this is that changes which are made by operations in the called function would be reflected in the calling function. Arrays in C are passed by reference (by default) as you would pass the array variable to the function which is actually a pointer to the first element of the array.
When you write int ** it actually means you are pointing to an address which is pointing to an element (Hence the **). So if you want to access an integer element of the array you would need to de-reference twice. For the case here:
zd: It is the pointer to the 1st row of the 2D array
zd + i: It is the pointer to the ith row of the 2D array
*(zd + i)/ zd[i]: De-references zd + i to give the address of the base element of the ith row.
Similarly zd[i][j] adds j to the base of the ith row and dereferences it to give the value of the element at ith row and jth column.
Here rules of addition are governed by pointer arithmetic, meaning since an integer occupies 4 bytes of data and if memory is byte organized a pointer to an integer when incremented by 1 would point 4 units ahead of what it pointed to earlier.
Your function initZD doesn't change the pointer int **zd which is passed by value. It not even changes the values of the pointer array where zd points to, but only the values where those pointers point to.
The pointer int **zd = NULL; in main is modified in main only because you allocate the memory there with
zd = malloc(width*sizeof(int));
You would have to pass the address of the pointer to initZD if you would want to allocate the memory inside the function.
Your code contains an error: In main you call free(zd) before you use it to free the other memory with free(zd[x])in the loop. This is undefined behavior.
Example where you would need to pass the pointer by reference, i.e. pass the address of the pointer:
void initZD(int ***zd, int width, int height){
*zd = malloc(width*sizeof(int));
for(int i = 0; i < width; i++){
(*zd)[i] = malloc(heigth*sizeof(int));
}
for(int i = 0; i < width; i++){
for(int j = 0; j < height; j++){
(*zd)[i][j] = rand() % 10;
}
}
return;
}
/* ... */
int main(){
int **zd = NULL;
int width, heigth;
printf("Width: ");
scanf("%d", &width);
printf("Heigth: ");
scanf("%d", &heigth);
initZD(&zd, width, heigth);
printZD(zd, width, heigth);
for(int x = 0; x < width; x++){
free(zd[x]);
}
/* NOTE you must not free this pointer before the loop above */
free(zd);
return 0;
}

Valgrind Invalid read of size 4 segfault

For an project assignment, I have this following variable from an prototype function which is not allocated.
int **suff;
This variable will receive a pointer to an array (int *) from a function which will generated an array of (int) from a FILO list (file).
(p is just a content structure, p->suff is a file)
int t = file_size(p->suff);
/* Prototype of file_tabint is
* int * file_tabint(file *p, int * psize)
*/
// Assign the generated array to the *suff)
*suff = file_tabint(p->suff, &t);
Now, when I want to print the array, valgrind raise a "invalid read of size 4"
for (int i = 0; i < t; i++) {
printf("%d -- ", *suff[i]);
}
My question is, what I did wrong in order to access to the int value of the array?
Note : I can't change the int **suff
The problem is *suff[i]. The way operator precedence works, that does suff[i] first and then dereferences whatever it finds there. You want to do it the other way round, so add brackets:
for (int i = 0; i < t; i++) {
printf("%d -- ", (*suff)[i]);
}

How to Store Multiple Arrays Returned From Pthread in Another Array Using Pointers

I'm working on a project that needs to run multiple threads concurrently. Each thread runs a function that returns a pointer to an array of ints (cast as a void pointer). For example, in the function that the threads run, the values I want are stored as such:
void *func(void *args) {
int vals[3] = {0, 0, 0}, x = y = z = 0;
int *ptr = vals;
while(condition) {
.
.
.
ptr[0] += x;
ptr[1] += y;
ptr[2] += z;
}
return (void *) ptr;
}
By the end of this function, ptr[0], ptr[1], and ptr[2] hold the desired values. This code is just to give you an idea of whats happening, there is nothing wrong with my actual implementation.
I am required to use pthread_join() to get the various values from each thread. Each thread handles one file, so # of files == # of threads == # of times the above function runs.
I need to take the values of ptr[0], ptr[1], and ptr[2] from each thread and add them together once they are returned to main. Meaning if there are three threads, then I need to add ptr[0] from thread 1 to ptr[0] from thread 2 and ptr[0] from thread 3. The same thing goes for ptr[1] and ptr[2]. Then I need to print the three total values in main at the end. So far this is how I've done it and I got my code to compile but the values are garbage.
int main(int argc, char *argv[]) {
int NUM_THREADS = argc - 1;
int total1 = total2 = total3 = 0;
pthread_t *tids; /* Dynamically allocated array of pthreads */
void **vals; /* Stores the return values from each thread, this could be incorrect */
/*
** Some code where I allocate the arrays etc
*/
for (i= 0; i < NUM_THREADS; i++)
pthread_create(&tids[i], NULL, func, NULL);
for (i= 0; i < NUM_THREADS; i++)
pthread_join(tids[i], &(vals[i])); /* Again, this could be wrong */
for (i= 0; i < NUM_THREADS; i++) {
total1 += ((int*) vals[i])[0]; /* These statements very well could also be wrong */
total2 += ((int*) vals[i])[1];
total3 += ((int*) vals[i])[2];
}
/* Print totals */
return 0;
}
I know the values in each thread are correct at the end of func, but I don't know how to properly store, process, and print them in main.
Also, I am using C90 and cannot use any functionality from any other version of C and I must store the values using pthread_join().
Each thread runs a function that returns a pointer to an array of ints (cast as a void pointer). For example
void *func(void *args) {
int vals[3] = {0, 0, 0}, x = y = z = 0;
int *ptr = vals;
...
return (void *) ptr;
}
You should start by fixing the function to return something meaningful. As currently written, the function returns a pointer to automatic array vals, which no longer exists after the function returns.
Any use of the returned pointer will produce undefined behavior.
This code is just to give you an idea of whats happening, there is nothing wrong with my actual implementation.
It's somewhat hard to believe that.
pthread_join(tids[i], &(vals[i])); /* Again, this could be wrong */
That is wrong: vals is uninitialized at this point, so you are writing all over random memory.
I don't know how to properly store, process, and print them in main.
Here is how:
void *vals[NUM_THREADS];
..
for (i= 0; i < NUM_THREADS; i++) {
pthread_join(tids[i], &vals[i]);
}
for (i= 0; i < NUM_THREADS; i++) {
int *p = (int *)vals[i];
total1 += p[0];
total2 += p[1];
... etc.
}

C Pointers - Structs that are arrays

I have been working on this code for a few hours now and am confused as to why printf is only printing garbage, I am brand new to stack overflow and fairly new to C so please forgive me for any mistakes in this post. I researched for pointers to structs that are arrays and couldn't find anything helpful.
typedef struct my
{
int x;
int y;
} My;
My * main2(void);
void show(void)
{
My * m = main2();
printf("%u\n", m);
printf("%u\n", m);
printf("%d\n", m->x);
printf("%d\n", m->y);
m++;
printf("%u\n", m);
printf("%d\n", m->x);
printf("%d\n", m->y);
m++;
printf("%u\n", m);
printf("%d\n", m->x);
printf("%d\n", m->y);
}
My * main2(void)
{
My j[3];
j[0].x = 2;
j[0].y = 4;
j[1].x = 3;
j[1].y = 5;
j[2].x = 7;
j[2].y = 9;
printf("%u\n", j);
return j;
}
int main()
{
show();
return 0;
}
Variables defined inside a function only have the life-time of that function. Once the function returns, the variables in essence cease to exist.
Now, if you return a pointer to such a variable (or to the first element of an array like you do) and that data no longer exists, then you get undefined behavior when you try to use the pointer.
One way to solve a problem like this is to pass the array (or, again, a pointer to its first element) as an argument to the function:
void main2(My *j)
{
j[0].x = 2;
// And so on...
}
And to pass an array to the function, remember that arrays decays to pointers to their first element when used in a context where a pointer is expected.
That means you could pass it like just about any other variable:
My arr[3];
main2(arr); // equal to main2(&arr[0]);
On another note, the format to print a pointer using printf is "%p". The pointer need to be casted void * as well:
printf("%p\n", (void *) j);
why printf is only printing garbage ? It's because of you are returning the address of a local variable here
My j[3];
...
...
return j; /* j is a local array, its scope is within this this function not outside */
your compiler could have warn you like this
function returns address of local variable [-Werror=return-local-addr]
To overcome this, you can create dynamic array & return it.
Also while printing m which structure pointer, use %p instead of %u format specifier. for e.g
printf("%p\n", (void*)m);
Alright I got the answer, I forgot about this really really important everything in the function is "gone" after the function has returned, thank you to both of the people that helped answer this :)
typedef struct my
{
int x;
int y;
} My;
void getData(My * pos)
{
printf("%d", pos->x);
printf("%d", pos->y);
pos++;
printf("%d", pos->x);
printf("%d", pos->y);
}
int main()
{
My x[2];
x[0].x = 3;
x[0].y = 4;
x[1].x = 5;
x[1].y = 6;
getData(x);
return 0;
}

I add values into a C array in one function, array is still empty in later function, what gives?

The pointer is declared
int *v;
And the two functions are called.
createMemObjects(M, N, v, context);
transferToDevice(M, v, commands);
So in my first function which I pass int *pv into, I fill the array:
pv = malloc(sizeof(int) * M);
memset(pv, 0, sizeof(int)*M);
for (int i = 0; i<M; i++) {
pv[i] = N; //Initialise every element of vector with N.
printf("Element %d: %d\n", i, pv[i]);
}
The print shows that pv has been filled with N=2.
In a later function which *pv as an argument again, I use a similar print loop:
for (int i = 0; i<M; i++) {
printf("Element %d: %d\n", i, pv[i]);
}
And instead of 2s, it shows all elements to be back to 0. What am I doing wrong? Pretty sure I've been using pointers correctly, but is there something I've missed?
As commented, you need to pass the address of the pointer v as C passes arguments by value, including pointers. As the code stands, a copy of v is being assigned within createMemObjects() so the change is not visible to the caller:
/* Invoke as */
createMemObjects(M, N, &v, context);
Change argument type of v to int** and within createMemObjects():
*pv = malloc(sizeof(int) * M);
The memset() immediately after malloc() is superfluous as the for is initalizing each int in pv.

Resources