Malloc-ating inside a Function vs malloc-ating in Main - c

I have a struct that contains an int pointer
struct mystruct {
int *myarray;
};
I want to make a function that mallocates for mystruct and also initializes myarray. But, when I try to access an element of myarray, I get a seg. fault
void myfunction(struct mystruct *s, int len) {
s = malloc(sizeof(mystruct));
s->myarray = malloc(sizeof(int) * len);
int i;
for (i=0; i<len; i++) {
s->myarray[i] = 1;
}
}
main() {
struct mystruct *m;
myfunction(m, 10);
printf("%d", m->myarray[2]); ////produces a segfault
}
However, mallocating m in main seemed to solve my problem.
Revised Code:
void myfunction(struct mystruct *s, int len) {
int i;
s->myarray = malloc(sizeof(int) * len);
for (i=0; i<len; i++) {
s->myarray[i] = 1;
}
}
main() {
struct mystruct *m = malloc(sizeof(mystruct)); //this was in myfunction
myfunction(m,10);
printf("%d", m->myarray[2]); ///Prints out 1 like I wanted
}
Why did the 2nd attempt work and why did the first attempt not work?

The problem is that the first version assigns the result of malloc to a parameter, which effectively a local variable; the assigned value vanishes when the function returns
So, an alternative is to pass to the function a pointer to the location where you want to store the result of malloc. This is named pps in the code below. At the beginning of the function we do the malloc and assign to a local variable s. Then we do things with s. Then, just before the function exits, we assign the local variable s to the location pointed to by the parameter pps. *pps = s;
void myfunction(struct mystruct **pps, int len) { // note double "**"
struct mystruct *s = malloc(sizeof(mystruct);
s->myarray = malloc(sizeof(int) * len);
int i;
for (i=0; i<len; i++) {
s->myarray[i] = 1;
}
*pps = s; // now pass the alloc'ed struct back to main through parameter pps
}
Now, back in main we pass &m to the function. This passes a pointer to m to the function. When the function returns, the local variable m holds the value returned by malloc and passed through the parameter pps.
main() {
struct mystruct *m;
myfunction(&m, 10); // PASS THE ADDRESS OF m, not m itself
printf("%d", m->myarray[2]); // this will work now
}

Related

How to fill an array of structs in a function [duplicate]

This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 4 years ago.
I'm trying to create an array of a structure in an external function "add", and print it's fields, but when I get back to the main function "arr" it is still NULL.
I'm confused because I've been creating arrays in external functions many times and it worked.. probably this time the dynamic memory allocation is messing the things up. Can I please get an advice on this matter?
Thanks!
typedef struct {
char* id;
char gender;
char *name;
}Member;
void add(Member arr[], int size);
void print(Member arr[], int *size);
int main()
{
char temp[100];
int size=0;
Member *arr = NULL;
Member *data = (Member*)malloc(sizeof(Member));
//scan fields
gets(temp);
data->id = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->id, temp);
gets(temp);
data->gender = temp;
gets(temp);
data->name = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->name, temp);
add(data, &arr, &size);
print(arr, &size);
return 0;
}
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
void print(Member arr[], int *size)
{
for (int i = 0;i < *size;i++)
{
puts(arr->id);
puts(arr->gender);
puts(arr->name);
}
}
Imagine code like this:
#include <stdio.h>
void f(int i){
i++;
}
int main(){
int i = 3;
f(3);
printf("%d\n", i);
}
We all know that f() incremented its local copy of i, not the variable that was passed into f() to initially set that value. With that having been said, let's take another look at your add():
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
When arr is passed into the function, it contains a memory address of the current arr, which starts as NULL. But just like when we change the local value of i in f() above, setting arr to a new value within add() only changes the local value; it does not change main()'s arr.
We also know that if we pass a function an address of data we want it to change, the function can then change the data at that address and the data at that address will reflect the change in the calling function:
#include <stdio.h>
void f(int * i){
*i = *i + 1;
}
int main(){
int i = 3;
f(&i);
printf("%d\n", i);
}
The same logic applies ( though it gets more confusing) when you want to change a pointer's value; send that pointer's address! Let's start with a very simple case:
#include <stdio.h>
#include <stdlib.h>
void f(int** i){
*i = (int*)malloc(sizeof(int));
**i = 99;
}
int main(){
int *i = NULL;
f(&i);
printf("%d\n", *i);
}
Here we create a pointer to an int in main, and initialize it to NULL. Then we send the address of that pointer (that is, the address we stored the NULL) to f(), which (like in your program) allocates some memory and puts the address of the newly allocated pointer _at the address of main's i. Now, the data stored at &i has changed, and dereferencing i from main() will dereference the newly allocated address.
In your code, just as in mine, you'll have to change the way you're passing arr to add() as well as how you interact with it - an exercise you'll get the most out of thinking through yourself. But in short, something like this should get you started:
pass add arr's address, not the address it stores.
Store new address of reallocated memory back to the same address, that is, &arr
make sure to update add() to dereference the pointer to a pointer twice to set the member at the address stored at the address &arr.

Why do I get dereferencing pointer errors?

I'm currently doing a C programme which requires the use of pointers, which I'm not great at.
I'm currently getting 4 errors which all say 'dereferencing pointer to incomplete type' and I don't know why.
Here is an example of how I set up my pointers and where I get the errors.
struct myset
{
unsigned char *vector;
int size;
int size_in_bytes;
int size_in_bits;
};
struct myset* set_new(int size)
{
int i;
struct myset* s;
s= malloc (sizeof (struct myset));
s->vector=malloc(sizeof(char)*(size/(sizeof(char)*8))+1);
for(i=0; i<size; i++)
{
s->vector[i]=0;
}
s->size_in_bits=size;
s->size_in_bytes=(size/(sizeof(char)))+1;
return s;
};
and I get an error whenever I try to reference the pointer, for example in this function.
void bitset_intersect(struct bitset * dest, struct bitset * src1, struct bitset * src2)
{
int maxSize = dest -> size_in_bits;
int i;
int j;
for(i = 0; i<maxSize; i++)
{
for(j = 0; j<maxSize; j++)
{
if(bitset_lookup(src1, i) == bitset_lookup(src2, j))
{
bitset_add(dest,i);
}
}
}
}
The error is in the line int maxSize = dest -> size_in_bits;
Any help would be appreciated, thanks.
Without the function call, its slightly hard to tell if you are passing the right values as parameters.
If you are getting an error while trying to reference the pointer, then check the function call to make sure you are passing the address correctly. Doing so would remove this error.
Both *dest and *src should have address that is being passed into it since both are from the same struct bitset.

Functions that only return variables in C

I want to call a function that will initialize an array and an integer variable and send them back from the function to the main program. I want to do that without even declaring those variables in the main program, but if I have to, then without initializing them in the main program. Is that even possible?
My C is rusty (haven't written any in ~17 years), but you'd probably do it with a struct (or a typedef'd struct) that the function returns:
struct foo {
int i;
int * a;
};
struct foo * myFunction() {
struct foo * pf;
pf = malloc(sizeof(*pf));
pf->i = 0; // Or whatever value it should have
pf->a = malloc(100 * sizeof(*pf->a)); // Or whatever size it should have
// ...fill in pf->a here...
return pf;
}
...or something like that. Usage:
struct foo * pf = myFunction();
You'd probably want a function to release it, too, e.g.:
struct foo * releaseFoo(struct foo * pf) {
if (pf != NULL) {
if (pf->a != NULL) {
free(pf->a);
pf->a = NULL;
}
free(pf);
}
return NULL;
}
Usage:
pf = releaseFoo(pf);
(You don't need the return type and such, but it's really handy to have it so you can assign to the pointer you're freeing, so you don't have dangling pointers to freed memory.)
Just a simple example for your requirement.
void func(int *a)
{
int i;
for(i=0;i<10;i++)
a[i] = i;
return;
}
int main()
{
int a[10],i;
func(a);
for(i=0;i<10;i++)
printf("%d",a[i]);
return 0;
}
Or
int *func()
{
int i;
int *p = malloc(sizeof(int) *10);
for(i=0;i<10;i++)
p[i] = i;
return p;
}
int main()
{
int i;
int *a = func();
for(i=0;i<10;i++)
printf("%d",a[i]);
return 0;
}

Creating function out of realloc() function

I would like to create a function that will reallocate 2D array of typedef struct
typedef struct hero_data{
char name[254];
char title[254];
int encoding;
int startstr;
double incstr;
int startdex;
double incdex;
int startintel;
double incintel;
int basemindmg,basemaxdmg;
double bat;
double basearmor;
struct hero_data *next;
struct hero_data *Class;
}hero;
typedef struct parameters{
int toughtotal;
int nimbletotal;
int smarttotal;
int skeptictotal;
int mystictotal;
int cursedtotal;
int brutetotal;
int shreddertotal;
int vanillatotal;
int typetotal;
int typenum;
hero **smart[];
hero **nimble[];
hero **tough[];
hero **type[][];
hero **skeptic[][];
hero **mystic[][];
hero **cursed[][];
hero **brute[][];
hero **shredder[][];
hero **vanilla[][];
}Parameters;
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p = realloc(p,sizeof(Parameters *) * typenum);
for ( i = 0; i < typenum; i++)
{
p[i] = realloc(p[i],sizeof(Parameters) * typetotal);
}
}
The function above shall be called like: void reallocation(p->type,p->typenum,p->typetotal);
So, by substituting the parameters of the function correctly, I expect the function to look like:
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p->type = realloc(p->type,sizeof(Parameters *) * p->typenum);
for ( i = 0; i < p->typenum; i++)
{
p->type[i] = realloc(p->type[i],sizeof(Parameters) * p->typetotal);
}
}
The typedef struct named Parameters contains int typenum, int typetotal, and the 2D arrays that shall be initialized through realloc().
When I try to compile, I am getting an error in Tiny C (Windows): *The file is in C.
Error: cannot cast 'struct parameters' to 'void *'
(This apeears in the 'p[i] = realloc(p[i],sizeof(Parameters) * typetotal')
Can anyone help me re-write this function so that I will be able to realloc the 2D arrays within the Parameter *p?
I tried changing void reallocation(Parameters *p, ...) into void reallocation(Parameters *p[], ...) and the Error # 2 becomes the same message as Error #1 and it appears in the = of p[i] = realloc (...);
A large problem with your code is that you are assigning inequal types to each other, and you are also not checking the result of realloc. If this call were to fail, you will leak the memory allocated initially.
Assuming that your struct looks like
typedef struct {
int typenum;
int typetotal;
} Parameters;
Parameters *p;
p = malloc(10 * sizeof(*p));
if (p == NULL)
printf("Allocatation of memory failed!\n");
To properly reallocate to say 20, you could do something like this
reallocate_p(&p, 20);
Where the function is defined as
void reallocate_p(Parameters **p, int new_size)
{
Parameters *temp;
temp = realloc(*p, sizeof(*temp) * new_size);
if (temp==NULL) {
printf("Reallocatation of memory failed!\n");
// Handle error
}
*p = temp;
return;
}
Also note that we don't cast the return value of malloc() and realloc().
As to why, see this reference
OP is coding in C, but using a using a C++ compiler.
Code in C++
// C
// p = realloc(p,sizeof(Parameters *) * typenum);
// C++
p = (Parameters *) realloc(p,sizeof(Parameters *) * typenum);
OR
VS2012: set properties for each C file to use C compiler
How to compile C in visual studio 2010?
OP code has a memory leak when scaling down the pointer array table. The pointers in the table that are about to be loss due to realloc() need to be freed first.
for (i=old_typenum; i<typenum; i++) free(p[i]);
p = realloc(p,sizeof(Parameters *) * typenum);

how to return 1000 variables from a function in C?

How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.

Resources