this code allocates a matrix by means of a series of function calls, but when i print it, it return a segmentation fault error.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void mat_init(int** matx);
void pp_init(int** matx);
void p_init(int** matx);
void mat_fill(int** matx);
void mat_print(int** matx);
int main(void)
{
srand((unsigned)time(NULL));
int** matrix;
mat_init(matrix);
mat_print(matrix);
return 0;
}
void mat_init(int** matx)
{
pp_init(matx);
}
void pp_init(int** matx)
{
matx=malloc(4*sizeof(int*));
p_init(matx);
}
void p_init(int** matx)
{
for(int i=0;i<4;i++)
{
*(matx+i)=malloc(4*sizeof(int));
}
mat_fill(matx);
}
void mat_fill(int** matx)
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
*(*(matx+i)+j)=rand()%5;
}
}
//mat_print(matx);
}
void mat_print(int** matx)
{
printf("The matrix is:\n");
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
printf("%1i|",*(*(matx+i)+j));
}
puts("");
}
puts("");
}
note that this happens only if i print the matrix using mat_print() int the main, if i use it in the function mat_fill() it works correctly, showing that it's been properly initialized.
What's the problem?
Essentially what you're doing is this:
void foo(int a);
{
a = 6;
}
int main()
{
int a = 3;
foo(a);
printf("a = %d\n", a); // expecting this to print 6
return 0;
}
Everything in C is pass by value, so that means anytime a parameter is passed to a function, a local copy of it is made in that function, and its scope exists only in that function; there is no exception for pointers. If I have this code instead:
void foo (int* ap2)
{
// there are now 2 pointers in memory that point to the same thing (main's a), namely
// ap2 on this stack frame and ap1 in the previous stack frame.
*ap2 = 6;
// ap2 is local to this function, but it _points_ to the same thing as
// ap1, so when we dereference it, changes to _what it points to_ are seen
// outside of this function. But once we return from this function, ap2
// ceases to exist
}
int main()
{
int a = 3;
int* ap1 = &a;
foo(ap1);
printf("a = %d\n", a); // now this prints 6
return 0;
}
If you want to manipulate main's matx in a function, then you need to pass a pointer to it and dereference it in that function in order to modify what it points to.
void foo (int*** matxp)
{
// matxp now points to matx in main
// dereference it here
*matxp = malloc(4 * sizeof(int*));
}
int main()
{
int** matx;
foo(&matx); // pass the address of matx here, which is an int*** type
....
// don't forget to clean up everything
return 0;
}
But as I said in the comments, I've rarely/never seen 3 star pointers. Instead you could just return the value
int** foo()
{
matxp = malloc(4 * sizeof(int*));
return matxp; // this will return NULL if malloc failed
}
int main()
{
int** matx = foo();
....
// do work, cleanup
return 0;
}
You need to do this:
int** mat_init(int** matx);
int** pp_init(int** matx);
int main(void)
{
matrix=mat_init(matrix);
}
int** mat_init(int** matx)
{
return pp_init(matx);
}
int** pp_init(int** matx)
{
matx=malloc(4*sizeof(int*));
p_init(matx);
return matx;
}
I omitted some lines that I didn't change. Another option is this:
void mat_init(int*** matx);
void pp_init(int*** matx);
int main(void)
{
mat_init(&matrix);
}
void mat_init(int*** matx)
{
pp_init(matx);
}
void pp_init(int*** matx)
{
*matx=malloc(4*sizeof(int*));
p_init(*matx);
}
Another thing: You're using the value 4 on a lot of places. That's dangerous. use a constant instead.
#define MAT_SIZE 4
void mat_fill(int** matx) {
for(int i=0;i<MAT_SIZE;i++) {
for(int j=0;j<MAT_SIZE;j++)
Related
I've got a struct that contains a pointer to function and an array of pointers to function. I'm passing the first pointer (not the array) as parameter of a function which is supposed to tell me whether an array of integers is sorted or not (it can be in ascending or descending order and this is defined by compFct, which is the pointer to function given in parameter).
Unfortunately that function is changing the values in the array of pointers in my struct (without changing the value of my pointer to function given in parameter).
Using gdb I managed to know when were made the changes in my array. It appears to be modified after the first printf in the printSorted function.
My typedef :
typedef int (*PtrCompFct)(int, int);
typedef int (*PtrSortFct)(int*, int, int, PtrCompFct);
The struct :
typedef struct
{
int nbFct;
PtrCompFct compFct;
PtrSortFct *sortFct;
} SortCompFct_s;
Here is how I'm calling my function (userChoices is of SortCompFct_s type):
printSorted(myArr, myArrSize, userChoices->compFct);
And the fonction that is changing my structure :
int printSorted(int *arr, int arrSize, PtrCompFct compFct)
{
for (int i=0; i<(arrSize-1); i++)
{
if (compFct(arr[i+1], arr[i]))
{
//this is when my array of pointers to function is modified
printf("The array isn't sorted\n\n");
return 0;
}
}
printf("The array is sorted\n\n");
return 1;
}
With gdb before the printf I have :
(gdb) print main::userChoices->sortFct[0]
$36 = (PtrSortFct) 0x5555555548ea <quickSort>
and after :
(gdb) print main::userChoices->sortFct[0]
$37 = (PtrSortFct) 0x7fffffffddc0
As you can see the pointer to my quickSort function has been modified.
EDIT : include of the simplified and verifiable code, the thing is that this code is working properly, even with the printSorted function
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int (*PtrCompFct)(int, int);
typedef int (*PtrSortFct)(int*, int, int, PtrCompFct);
typedef struct
{
int nbFct;
PtrCompFct compFct;
PtrSortFct *sortFct;
} SortCompFct_s;
typedef SortCompFct_s *PtrSortCompFct_s;
void initTab(int *arr, int arrSize)
{
time_t t;
srand(time(&t));
for (int i=0; i<arrSize; i++)
{
arr[i] = rand();
}
}
int ascendingSort(int elmt1, int elmt2)
{
return (elmt1 < elmt2);
}
int descendingSort(int elmt1, int elmt2)
{
return (elmt1 > elmt2);
}
void switche(int *arr, int ind1, int ind2)
{
int temp = arr[ind1];
arr[ind1] = arr[ind2];
arr[ind2] = temp;
}
int bubbleSort(int *arr, int ind1, int ind2, PtrCompFct fctComp)
{
int sorted;
for (int i=ind1; i<ind2; i++)
{
sorted = 1;
for (int j=0; j<ind2; j++)
{
if (fctComp(arr[j+1], arr[j]))
{
switche(arr, j, j+1);
sorted = 0;
}
}
if (sorted) return 0;
}
return 0;
}
void printArr(int *arr, int arrSize)
{
for (int i=0; i<arrSize; i++)
{
printf("%16d\n", arr[i]);
}
}
int printSorted(int *arr, int arrSize, PtrCompFct compFct)
{
for (int i=0; i<arrSize-1; i++)
{
if (compFct(arr[i+1], arr[i]))
{
//this is when my array of pointers to function is modified
printf("The array isn't sorted\n\n");
return 0;
}
}
printf("The array is sorted\n\n");
return 1;
}
PtrSortCompFct_s menu(void)
{
PtrSortCompFct_s userChoices;
PtrSortFct arrSortFct[] = {bubbleSort};
if ((userChoices = malloc(3*sizeof(int))) != NULL)
{
userChoices->nbFct = 1;
userChoices->compFct = ascendingSort;
userChoices->sortFct = arrSortFct;
}
return userChoices;
}
int main(void)
{
int arrSize = 10;
int arr[arrSize];
initTab(arr, arrSize);
PtrSortCompFct_s userChoices;
if ((userChoices = malloc(3*sizeof(int))) != NULL) userChoices = menu();
printArr(arr, arrSize);
printSorted(arr, arrSize, userChoices->compFct);
userChoices->sortFct[0](arr, 0, arrSize-1, userChoices->compFct);
printArr(arr, arrSize);
printSorted(arr, arrSize, userChoices->compFct);
return 0;
}
With gdb before the printf I have: ... and after:
The root cause of your problem is in how you have initialized userChoices->sortFct (you have not shown the code which performs this initialization).
That array is pointing to dangling heap or stack memory, and a call to printf overwrites that memory.
if ((userChoices = malloc(6*sizeof(int))) != NULL) userChoices = menu();
That code is completely bogus: heap-allocating memory for userChoices and then immediately overwriting userChoices with return value from menu() only serves to leak memory. As mentioned in the comments, 6*sizeof(int) is also completely bogus size.
I would guess that your menu() looks something like this:
struct SortCompFct_s* menu()
{
struct SortCompFct_s ret;
ret.compFct = &SomeFunc;
ret.sortFct = malloc(...);
ret.sortFct[0] = &quickSort;
return &ret; // Oops: returning address of a local!
}
If that is in fact what you did, dangling stack is exactly your problem. You should turn on maximum compiler warnings (-Wall -Wextra if using GCC), so the compiler tells you you are doing something wrong.
Update:
My guess was close:
PtrSortCompFct_s menu(void)
{
PtrSortCompFct_s userChoices;
PtrSortFct arrSortFct[] = {bubbleSort};
if ((userChoices = malloc(3*sizeof(int))) != NULL)
{
userChoices->nbFct = 1;
userChoices->compFct = ascendingSort;
userChoices->sortFct = arrSortFct;
}
return userChoices;
}
The problem is that userChoices->sortFct points to a local (stack) variable arrSortFct. That local variable becomes invalid after return from menu, and at that point userChoices->sortFct is pointing to dangling stack (as I guessed).
Here is correct way to write this function (omitting error checking of malloc return for clarity):
PtrSortCompFct_s menu(void)
{
PtrSortCompFct_s userChoices;
PtrSortFct arrSortFct[] = {bubbleSort};
if ((userChoices = malloc(sizeof(*userChoices)) != NULL)
{
userChoices->nbFct = 1;
userChoices->compFct = ascendingSort;
userChoices->sortFct = malloc(sizeof(arrSortFct));
memcpy(userChoices->sortFct, arrSortFct, sizeof(arrSortFct));
}
return userChoices;
}
You should also need to fix your main like so:
PtrSortCompFct_s userChoices;
PtrSortCompFct_s userChoices = menu();
... use userChoices ...
free(userChoices->sortFct);
free(sortFct);
return 0;
I'm writing a program that can modify rows and cols from a function of a function. I don't understand how to do pointer of a pointer.
void changeNum(int*setRows, int *setCol)
{
changeNum2(*setRows,*setCol);
}
void changeNum2(int*setRows, int *setCol)
{
*setRows=5;
*setCol=5;
}
int main() {
int*row=10;
int* col=10;
changeNum(&row,&col);
printf("%d %d",row,col);
return 0;
}
First
int*row=10;
int* col=10;
This is wrong. Assigning hardcoded address. You don't want this
int row=10;
int col=10;
How to get the address of the row and col?
&row and &col.
How to pass it to function?
Call it, changeNum(&row,&col);
void changeNum(int*setRows, int *setCol)
{
...
}
How to pass pointer to pointer?
void changeNum(int*setRows, int *setCol)
{
chnageNum2(&setRows, &setCol);
}
ChangeNum2 how it would change value?
void chnageNum2(int **setRows, int **setCol){
**setRows = 110;
**setCol = 110;
}
Can we do the same change using changeNum() only?
Yes we can do that.
void changeNum(int*setRows, int *setCol)
{
*setRows = 110;
*setCol = 110;
}
Definitely check this. Grab a book. It will help a lot.
The complete code will be
void changeNum(int*setRows, int *setCol)
{
changeNum2(&setRows,&setCol);
}
void changeNum2(int**setRows, int **setCol)
{
**setRows=5;
**setCol=5;
}
int main(void) {
int row=10;
int col=10;
changeNum(&row,&col);
printf("%d %d",row,col);
return 0;
}
#include <stdio.h>
void changeNum(int*, int*);
void changeNum2(int*, int*);
void changeNum(int* setRows, int *setCol) {
changeNum2(setRows,setCol);
}
void changeNum2(int* setRows, int *setCol) {
*setRows=5;
*setCol=5;
}
int main() {
int row=10;
int col=10;
changeNum(&row, &col);
printf("%d %d\n", row, col);
return 0;
}
It takes sometime to grasp that every C function parameter is passed by value. So you can safely pass setRows pointer to the second function simply by its value.
Also, it's necessary to declare previously the function changeNum2, I've included the declaration without parameter names to clarify it's possible.
I strongly recommend reading this book: https://en.wikipedia.org/wiki/The_C_Programming_Language, specially chapter 5 (Pointers and arrays).
You can find a PDF copy easily. It's where I finally learned this concept.
I keep geeting a segfault in the main function. I create a pointer to a struct I created and I pass it's reference to another function which allocates and reallocates memory. Then accessing it in the main function (where it was originally defined) causes a segfault.
Here is my test code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char desc[20];
int nr;
} Kap;
void read(Kap *k);
int main(void) {
Kap *k = NULL;
read(k);
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
void read(Kap *k) {
int size = 3;
k = (Kap*) calloc(size, sizeof(Kap));
k[0].nr = 1;
k[1].nr = 2;
k[2].nr = 3;
strcpy(k[0].desc, "hello0");
strcpy(k[1].desc, "hello1");
strcpy(k[2].desc, "hello2");
size *= 2;
k = (Kap*) realloc(k, sizeof(Kap)*size);
if(k == NULL) {
printf("ERROR\n");
exit(EXIT_FAILURE);
}
k[3].nr = 4;
k[4].nr = 5;
k[5].nr = 6;
strcpy(k[3].desc, "hello3");
strcpy(k[4].desc, "hello4");
strcpy(k[5].desc, "hello5");
}
What am I doing wrong?
Here's a simplified version of the problem you are having:
#include <stdio.h>
void func(int x)
{
x = 10;
}
int main()
{
int x = 5;
printf("x = %d\n", x);
func(x);
printf("x = %d\n", x);
}
The same reason x does not change is the reason that k does not change in your program. A simple way to fix it is this:
Kap *read()
{
Kap *k = calloc(...);
...
k = realloc(k, ...);
...
return k;
}
int main()
{
Kap *k = read();
...
}
The problem is you're not passing the pointer back to main(). Try something like this instead:
Kap * read();
int main(void) {
Kap *k = read();
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
Kap * read() {
... everything else you're already doing ...
return k;
}
The code you showed passes a pointer by value into read(). The subroutine can use that pointer (though it's kind of useless since its local copy is immediately changed), however changes made within read() do not bubble back to its caller.
My suggestion is one method of allowing read() to send the new pointer back up, and it's probably the right method to choose. Another method is to change read()s signature to be void read(Kap **);, where it will receive a pointer to a pointer -- allowing it to modify the caller's pointer (due to being passed by reference).
This is giving me a segfault at the memset and I have no idea why, I am going to a specific index of a 2D array, this should give me a char pointer and allow me to use memeset.
void test(char** test)
{
int i;
for(i=0;i<20;i++)
{
memset(test[i],0,sizeof(char)*1);
return;
}
}
int main()
{
char thing[20][20];
int i;
for(i=0;i<20;i++)
{
memset(thing[i],0,sizeof(char)*20);
}
test(thing);
return 0;
}
Your parameter declaration is incorrect, it should be:
void test(char test[20][20])
or:
void test(char test[][20])
I am slowly learning how to program generic functions in C and get into trouble now and so often. I am making a program that makes a union of two arrays, in this implementation two int arrays. The first problem, which also leads to the second one, is that the compareints (function) does not access one of the passed arguments (void *): I can't figure out why? I been staring at the screen for to long time now...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//makes union of two generic arrays and eliminates duplicates if there are some...
void **
unite(int (*comp)(void *f, void *s), void **first, void **second, int f_size, int s_size, int bytes, int *x)
{
int i;
void **arr=malloc(bytes*(f_size+s_size));
for(i=0; i<f_size+s_size; i++)
{
/* first bigger */
if(((*comp)(*first, *second))>0)
{
*(arr+i)=*(first++);
}
/* second bigger */
else if(((*comp)(*first, *second))<0)
{
*(arr+i)=*((second++));
}
/* equal => just one copy */
else
{
*(arr+i)=*(first++);
second++;
}
}
*x=i;
return arr;
}
int
compareints(void *first, void *second)
{
if(*((int *)first)>*((int *)second)) //can't access the memoryloc in second...
return 1;
else if(*((int *)first)<*((int *)second))
return -1;
else
return 0;
}
int main(int argc, const char * argv[])
{
int arr[10]={1, 2, 4, 12, 22, 29, 33, 77, 98};
int arr2[5]={3, 5, 7, 8, 9};
void **first=malloc(sizeof(int *)*10);
void **second=malloc(sizeof(int *)*5);
//make pointers to static arrays in dynamic arrays
int f_ind, s_ind;
for(f_ind=0; f_ind<10; f_ind++)
first[f_ind]=&arr[f_ind];
for(s_ind=0; s_ind<5; s_ind++)
second[s_ind]=&arr2[s_ind];
int i;
//make union of the two arrays and print out the result
void **ret=unite(&compareints, first, second, 10, 5, sizeof(int), &i);
for(int k=0; k<i; k++)
printf("%d ", *((int *)ret[k]));
return 0;
}
Why can't function access generic parameter ?
Simple answer to this question is function can access but further manipulation on void * is not possible.
Elements are accessed using pointer arithmetic (which needs size of individual element) since the pointer which is void * pointing to the address you passed but doesn't know about the size of each field in that array or memory location. so accessing or dereferencing will lead you to Undefined Behaviour.
If you want to access each element of that type inside the function then , pass the size of individual element to that function and on that basis make pointer to that same type , then access using new pointer of that type.
For more read this
I tried an approach thanks to #WhozCraigs post about the index going out of bounds. So I made some small mods and now the program does what it intends to.
void **
unite(int (*comp)(void *f, void *s), void **first, void **second, int f_size, int s_size, int bytes, int *x)
{
int i;
int f_ind=0, s_ind=0;
void **arr=malloc(bytes*(f_size+s_size));
for(i=0; i<f_size+s_size; i++)
{
/* first bigger */
if(((*comp)(*first, *second))>0)
{
s_ind++;
if(s_ind<s_size)
*(arr+i)=*(second++);
else
{
f_ind++;
if(f_ind<f_size)
*(arr+i)=*(first++);
else
break;
}
}
/* second bigger */
else if(((*comp)(*first, *second))<0)
{
f_ind++;
if(f_ind<f_size)
*(arr+i)=*(first++);
else
{
s_ind++;
if(s_ind<s_size)
*(arr+i)=*(second++);
else
break;
}
}
/* equal => just one copy */
else
{
f_ind++;
s_ind++;
if(f_ind<f_size && s_ind==s_size)
{
*(arr+i)=*(first++);
}
else if(f_ind==f_size && s_ind<s_size)
{
*(arr+i)=*(second++);
}
else
{
*(arr+i)=*(first++);
second++;
}
}
}
*x=i;
return arr;
}