dynamic array declaration in different functions - c

Is it possible to declare a dynamic array in (main), but use malloc inside another function?
I mean something like this
.
.
int main(void)
{
.
.
int **array;
.
.
}
void function(int **arr)
{
.
array = (**int) malloc .......
.
}

Yes, it is possible but not like you suggest but like this:
int main(void)
{
.
int *array;
function(&array);
.
}
void function(int **arr)
{
.
*array = malloc(..) // no cast is needed here
.
}
And your unneeded (**int) cast is wrong, it should be (int*).
Read also this SO article which is almost a duplicate of your question.

Yes it is possible like this.
int main(void)
{
int *array;
function(&array);
}
void function(int **arr)
{
.
*arr = (int *) malloc .......
.
}

Yes, receiving a pointer to pointer:
void function(int **array, size_t elements)
{
*array = malloc(sizeof(int) * elements);
if (*array == NULL)
{
// raise error
}
}
int main(void)
{
int *array;
function(&array, 10);
return 0;
}
another option is return the address (the allocated space) from the function:
int *function(size_t elements)
{
int *array = malloc(sizeof(int) * elements);
if (array == NULL)
{
// raise error
}
return array;
}
int main(void)
{
int *array = function(10);
return 0;
}

Related

dynamically allocated matrix gives seg fault when printed

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++)

How to "return" an array from a function to main in c

I want to pass an arrays index from my function to main. How can I do that?
For example:
void randomfunction()
{
int i;
char k[20][10];
for (i=0;i<20;i++)
strcpy(k[i], "BA");
}
int main(int argc, char *argv[])
{
int i; for (i=0;i<20;i++) printf("%s",k[i]);
return 0;
}
I know that for you this is very simple but I've found similar topics and they were too complicated for me. I just want to pass the k array to main. Of course my purpose is not to fill it with "BA" strings...
You want to allocate the memory dynamically. Like this:
char** randomfunction() {
char **k=malloc(sizeof(char*)*20);
int i;
for (i=0;i<20;i++)
k[i]=malloc(sizeof(char)*10);
//populate the array
return k;
}
int main() {
char** arr;
int i;
arr=randomfunction();
//do you job
//now de-allocate the array
for (i=0;i<20;i++)
free(arr[i]);
free(arr);
return 0;
}
See about malloc and free.
Here is another option. This works because structs can be copied around , unlike arrays.
typedef struct
{
char arr[20][10];
} MyArray;
MyArray random_function(void)
{
MyArray k;
for (i=0;i<sizeof k.arr / sizeof k.arr[0];i++)
strcpy(k.arr[i], "BA");
return k;
}
int main()
{
MyArray k = random_function();
}
Simplest way:
void randomfunction(char k[][10])
{
// do stuff
}
int main()
{
char arr[20][10];
randomfunction(arr);
}
If randomfunction needs to know the dimension 20, you can pass it as another argument. (It doesn't work to put it in the [] , for historial reasons).

Sorting structure with C qsort()

Having trouble getting my head around implementing the qsort() built into C to sort an array of structs by a stored int value (hitCount).
My struct:
typedef struct words {
const char *word;
int hitCount;
} words;
I'm trying to use the example given by Microsoft (http://support.microsoft.com/kb/73853).
So I've got at the top:
typedef int (*compfn)(const void*, const void*);
and the comparision method:
int compare (words *a, words *b) {
if (a->hitCount > b->hitCount) {
return -1;
} else if (a->hitCount < b->hitCount) {
return 1;
} else {
return 0;
}
}
then within another method I call qsort with my array name and other details replacing the Microsoft example:
qsort((void *) &output, outputLength, sizeof(words), (compfn)compare);
This gives a segmentation fault.
I don't fully understand how to use qsort so I assume where I've adapted it from Microsoft's example I've done it incorrectly.
I hope I've included the mistake and can get some enlightenment as to what I should be doing in order for this to work correctly.
Many Thanks!
You have to pass the array not the address of the array to qsort.
qsort( output, ... );
Also your compare function must return an int and accept two const void* arguments.
Casting your function int compare (words *a, words *b) to a different( yet correct ) type which is then called by qsort() will cause undefined behaviour.
The compare function must be:
int compare (const void *a, const void *b)...
Then you cast a and b to correct types:
((words*)a)->hitCount < ((words*)b)->hitCount
I suspect that outputLength is computed incorrectly. A complete working example:
#include <stdio.h>
#include <stdlib.h>
typedef struct words {
const char *word;
int hitCount;
} words;
int compare(const void * left, const void * right) {
const words * a = (const words *) left;
const words * b = (const words *) right;
if (a->hitCount > b->hitCount) {
return -1;
} else if (a->hitCount < b->hitCount) {
return 1;
} else {
return 0;
}
}
int main() {
struct words output[] = {
{ "hello", 314 },
{ "world", 42 },
{ "answer", 42 }
};
int outputLength = sizeof(output) / sizeof(output[0]);
int i;
output[0].word = "hello";
output[0].hitCount = 314;
output[1].word = "world";
output[1].hitCount = 42;
qsort(output, outputLength, sizeof(words), compare);
for (i = 0; i < outputLength; ++i) {
printf("%d %s\n", output[i].hitCount, output[i].word);
}
return 0;
}
The prototype of the standard library function qsort is
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
Note the signature of the compare function. You cannot typecast a pointer to a function of different signature and make it work correctly. Therefore, typecasting your compare function will not work. It must have the same signature as declared in the prototype of qsort. Change your compare function to -
int compare(const void *a, const void *b) {
int c = ((words *) a)->hitCount;
int d = ((words *) b)->hitCount;
if(c > d) return -1;
if(c < d) return 1;
return 0;
}
The first argument base of qsort is the base address of the buffer which contains the elements to be sorted. Also, any pointer type is assignment compatible to a void * variable and as such you don't need to cast the base address. Therefore, you should call the qsort function as -
qsort(output, outputLength, sizeof output[0], compare);
Got it working with:
int compare (const void *a, const void *b) {
if (((words *)a)->hitCount > ((words *)b)->hitCount) {
return -1;
} else if (((words *)a)->hitCount < ((words *)b)->hitCount) {
return 1;
} else {
return 0;
}
}
and call to sort:
qsort(output, outputLength, sizeof(words), compare);
Thanks to everyone's help but majority credit to "self".

Memset not working in outside function

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])

Passing a parameter in a callback in C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do function pointers in C work?
Surfing on stackoverflow I found this example:
/* Validation functions start */
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue();
}
int getNextRandomValue(void)
{
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10, getNextRandomValue);
...
}
I was wondering, imagine getNextRandomValue had a parameter getNextRandomValue(int i), how would I include this and making the function accepting inputs?
Many thanks
Common practice is to pass a pointer to "data" together with the function. When function gets called, pass that "data" pointer into function and assume that the function itself knows what to do with that data. In fact the data is usually a pointer to a structure. So the code looks like this:
struct func1_data {
int a;
int b;
};
struct func2_data {
char x[10];
};
int function1(void *data) {
struct func1_data *my_data = (typeof(my_data)) data;
/* do something with my_data->a and my_data->b */
return result;
}
int function2(void *data) {
struct func2_data *my_data = (typeof(my_data)) data;
/* do something with my_data->x */
return result;
}
and assume we have
int caller(int (*callback), void *data) {
return callback(data);
}
Then you call all this like this:
struct func1_data data1 = { 5, 7 };
struct func2_data data2 = { "hello!" };
caller(function1, (void *) &data1);
caller(function2, (void *) &data2);
It's probably a good idea to get familiar with function-pointer syntax. You need to change the argument to int (*getNextValue)(int).
Then your code should be like this...
void populate_array(int *array, size_t arraySize, int (*getNextValue)(unsigned int))
{
unsigned int seedvalue = 100;
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue(seedvalue);
}
int getNextRandomValue(unsigned int seed)
{
srand(seed);
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10, getNextRandomValue);
...
}

Resources