Set structure pointer to NULL in function in C - c

I try to free structure pointer using function and then check for NULL. It doesn't work!
typedef struct{
int * num;
} D;
void freeD(D * a){
free(a->num);
free(a);
a=NULL;
}
int main(){
D * smth = malloc(sizeof(D));
smth->num = malloc(sizeof(int)*2);
freeD(smth);
if(smth==NULL){
printf("It's NULL");
}
}

You have to pass the pointer by reference that is by using pointer to the pointer.
For example
void freeD(D ** a){
free( ( *a )->num);
free(*a);
*a=NULL;
}
//...
freeD( &smth );

Here you have passed the parameter by value instead of passing the parameter by reference.
What have you done
Let us assume smth=0x0030;
where address(smth) = 0x0100 && value(smth) = 0x0030.
So when you do freeD(smth), you are actually passing value(smth) which is 0x0030. Meanwhile, in the function freeD():-
address(a) = 0x0200 && value(a) = 0x0030
So when you do set
a = NULL
you are actually setting the value(a) = NULL where address(a)=0x0200; instead of doing it at the address=0x0100;
What you should have done
void freeD(D ** a){
free((*a)->num);
free(*a);
*a=NULL;
}
int main(){
//...
freeD(&smth);
//...
}

Related

Table of structures (realloc in C)

i am trying to write a code in C but i am having some problems with realloc. I had to write a code that will create a stack, and will add to it (dodaj_do_stosu), reamove from it (usun_ze_stosu) and will look at the top thing that is on this stack. I have problem with compiling(it does work for first two words but then it returns (0xC0000374)).
I think i am usining the realloc wrong and the sizeof my structure. If someone could look at my code (especially at the function (dodaj_do_stosu) and tell me what am i doing wrong thx. My code look like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int n;
char *nazwa;
}element_t;
typedef struct {
int rozmiar;
element_t **tablica;
}stos_t;
void top_of_stack(stos_t *s){
printf("ostatni element stosu:rozmiar = %d nazwa=%s, n=%d\n", s->rozmiar, s->tablica[s->rozmiar]->nazwa, s->tablica[s->rozmiar]->n);
}
void init(stos_t *s)
{
s->rozmiar=0;
s->tablica=malloc(0);
}
void dodaj_do_stosu(stos_t *s, int n, char *name)
{
s->tablica = realloc(s->tablica, (s->rozmiar + 1) * sizeof(s->tablica));
s->tablica[s->rozmiar]->nazwa = name;
s->tablica[s->rozmiar]->n = n;
printf("rozmiar=%d, n=%d , nazwa=%s\n",s->rozmiar, s->tablica[s->rozmiar]->n, s->tablica[s->rozmiar]->nazwa);
s->rozmiar++;
}
void usun_ze_stosu(stos_t *s)
{
s->tablica = realloc(s->tablica, (s->rozmiar - 1) * sizeof(s->tablica[0]));
s->rozmiar--;
}
void rm(stos_t s)
{
free(s.tablica);
}
int main(int argc, char **argv)
{
stos_t s;
init(&s);
int i;
srand(time(0));
if (argc>1)
for(i=1;i<argc;i++){
printf("%s\n", argv[i]);
dodaj_do_stosu(&s, rand() % 10, argv[i]);
}
for(i=0;i<argc-1;i++){
//printf("i=%d, n=%d, nazwa=%s\n",i, s.tablica[i].n, s.tablica[i].nazwa);
}
//top_of_stack(&s);
//usun_ze_stosu(&s);
//top_of_stack(&s);
rm(s);
return 0;
}
A big part of your problem is that tablica is an array of pointers, but you never initialize the pointers themselves.
The dodaj_do_stosu function reallocates the array, but doesn't create the element_t objects. Therefore any dereference of e.g. s->tablica[s->rozmiar] will lead to undefined behavior.
There are two possible solutions:
Allocate a new element_t structure:
s->tablica[s->rozmiar] = malloc(sizeof(element_t));
before you initialize the element_t structure members.
Make tablica an array of structure objects instead of pointers:
element_t *tablica; // tablica is an array of objects, not an array of pointers
I recommend solution 2.
At least the function dodaj_do_stosu is wrong. The data member tablica is declared like
element_t **tablica;
So the expression s->tablica[s->rozmiar] has the type element_t * and an indeterminate value. Thus dereferencing the pointer expression for example like
s->tablica[s->rozmiar]->nazwa
invokes undefined behavior.
You have to allocate memory for objects of the structure type element_t not for pointers of the type element_t *.
So you need to declare the data member like
element_t *tablica;
and within the function to write
s->tablica = realloc(s->tablica, (s->rozmiar + 1) * sizeof( *s->tablica));
Also it is safer to use an intermediate pointer for calls of realloc.
The function can look the following way
int dodaj_do_stosu( stos_t *s, int n, char *name )
{
element_t *tmp = realloc( s->tablica, ( s->rozmiar + 1 ) * sizeof( *s->tablica ) );
int success = tmp != NULL;
if ( success )
{
s->tablica = tmp;
s->tablica[s->rozmiar]->nazwa = name;
s->tablica[s->rozmiar]->n = n;
printf("rozmiar=%d, n=%d , nazwa=%s\n", s->rozmiar, s->tablica[s->rozmiar]->n, s->tablica[s->rozmiar]->nazwa );
++s->rozmiar;
}
return success;
}
Consequently the function should be redefined at least the following way. As is it can for example invoke undefined behavior when s->rozmiar is equal to 0.
int usun_ze_stosu( stos_t *s )
{
int success = s->rozmiar != 0;
if ( success )
{
element_t *tmp = realloc( s->tablica, ( s->rozmiar - 1 ) * sizeof( *s->tablica ) );
success = tmp != NULL;
if ( success )
{
s->tablica = tmp;
--s->rozmiar;
}
}
return success;
}
Also within the function init it will be much better ro write
void init(stos_t *s)
{
s->rozmiar=0;
s->tablica = NULL;
}
Another problem is the function rm
void rm(stos_t s)
{
free(s.tablica);
}
You should pass the original object through a pointer to it and within the function to write
void rm(stos_t *s)
{
free( s->tablica );
s->tablica = NULL;
s->rozmiar = 0;
}

2D allocated array (fixed number of columns) as return value of a function

I would like some help with pointers:
in main function I have initialized variable that should point to the array:
int main() {
int n;
double (*array)[3];
array = fillArray(&n);
The function receives an integer argument, which counts number of rows. The return value of the function should be a pointer to the newly created array, which will be saved to the variable 'array' in main function:
double (*)[3] fillArray(int * n) {
double (*array)[3] = NULL;
int allocated = 0;
*n = 0;
while (1)
{
/*scanning input*/
if (allocated <= *n)
{
allocated += 10;
array = (double(*)[3]) realloc (array, sizeof(*array) * allocated)
}
array[*n][0] = value1;
array[*n][1] = value2;
array[*n][2] = value3;
(*n)++;
}
return array;
}
However, the type of return value isn't right and I am kinda lost. Can anyone tell me what is wrong in this code?
Thank you in advance :)
Your code has an unrelated syntax error and some undeclared variables, but the problem you asked about has to do with the form of the declaration of function fillArray(). This alternative works for me:
double (*fillArray(int * n))[3] {
double (*array)[3] = NULL;
/* ... */
return array;
}
Note the similarity in form to the declarations of your variables of the same type.
The problem is that although double (*)[3] is a perfectly valid type designator for use, say, in a cast, it is incorrect to use it quite as you tried to do to declare the type of an object.
given some guessing about items not mentioned in the question.
I think this is what you are looking for.
Notice the checking for success of the call to realloc()
Notice the #define of the magic numbers
#include <stdlib.h> // realloc(), exit(), EXIT_FAILURE
#define ALLOCATION_INCREMENT (10)
#define NUM_DOUBLES (3)
struct tagArray
{
double arrayEntry[ NUM_DOUBLES ];
};
struct tagArray *fillArray(int *n);
int main( void )
{
int n = 0;
struct tagArray *array;
if( NULL == (array = fillArray(&n) ) )
{ // then array generation failed
exit( EXIT_FAILURE );
}
// implied else, array generation successful
....
free( array );
return 0;
} // end function: main
struct tagArray *fillArray(int *n)
{
struct tagArray *array = NULL;
int allocated =0;
while( 1 )
{
/* scanning input,
* to acquire 'value1, value2, value3'
* with some key input causes execution of 'break;'
* */
if( allocated <= *n )
{
allocated += ALLOCATION_INCREMENT;
struct tagArray *temp = realloc (array, sizeof( struct tagArray) * allocated );
if( !temp )
{ // then realloc failed
free( array );
return( NULL );
}
array = temp;
}
array[*n][0] = value1;
array[*n][1] = value2;
array[*n][2] = value3;
(*n)++;
}
return array;
} // end function: fillArray

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;
}

How to return a pointer in a function?

I have just started learning about pointers and how they can be passed to functions as arguments, and how they can have the same effects as arrays in functions.
And now I am curious how to instead, return pointers in a function, or if this is possible? That is my question. I would like to know how to return a general pointer.
yes it is possible to return pointer from functions.
int * FunctionReturningAnInteger()
{
// this function returns integer pointer;
int *integerPointer = malloc(sizeof *integerPointer); /* memory allocation */
*integerPointer = 12;
return integerPointer;
}
char * FunctionReturningACharacter()
{
// this function returns integer pointer;
char*charPointer = malloc(sizeof *charPointer ); /* memory allocation */
*charPointer = 'a';
return charPointer ;
}
hope it's clear now to you
prototype for returning pointer
int* func();
float* func();
char* func();
Just define them whatever you want.
As I can deduce from the question, you are trying to get a tutorial from here which is obviously not possible. You have to try yourself the examples and most importantly, you have to understand the concept of returning a pointer from a function.
You can start with these questions::
When is returning pointer from a function good?
What do these pointers actually return ?
How to collect the returned pointer from a function ?
For instance you can compile and debug this example,
/* function to generate and retrun random numbers. */
int * getRandom( )
{
static int r[10];
int i;
/* set the seed */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i)
{
r[i] = rand();
printf("%d\n", r[i] );
}
return r;
}
/* main function to call above defined function */
int main ()
{
/* a pointer to an int */
int *p;
int i;
p = getRandom();
for ( i = 0; i < 10; i++ )
{
printf("*(p + [%d]) : %d\n", i, *(p + i) );
}
return 0;
}
int i;
/* returns a pointer to an int */
int *function1()
{
return &i;
}
char c;
/* returns a pointer to a char */
char *function2()
{
return &c;
}

how to pass the pointer to a function and assign the value to the variable pointed to in C?

I know the c always pass by values, but if I have a pointer:
int i = 4;
int * p;
p = &i;
then I have a function, how to pass pointer p to it and change the value of variable i?
void changeValue(int *p)
{
}
how to pass the pointer and change the variable pointed by p?
This simple example shows how to pass a pointer (i.e. not a value) and recieve back through that pointer, the new value held by the integer. Note the reduced number of variables. i.e. there is no need necessarily to create a separate copy of int *p;. Nor is it necessary in this case to initialize p: p = &i; to the address of i.
int changeValue(int *);
int main(void)
{
int i=15;
changeValue(&i);
return 0;
}
int changeValue(int *p) //prototyped to accept int *
{
return *p = 3;
}
If you do want to create a pointer in the first place, and pass that pointer, then:
int changeValue(int *);
int main(void)
{
int i=15;
int *p;
p = &i;
*p; // *p == 15 at this point
//since p is already a pointer, just pass
//it as is
changeValue(p);
return 0;
}
int changeValue(int *q) //prototyped to accept int *
{
return *q = 3;
}
It is important to note that your statement: I know the c always pass by values is not correct. It is more common for functions to be written such that pointers are passed because often a pointer is smaller, and more efficient to pass around than the actual variable, especially when large arrays, or structs are used. Keep in mind though that passing &i (the address of i) works just as well as passing p if passing a pointer is called for.
Simply pass it by calling changeValue as
changeValue(p);
and change the value of variable pointed by it (i) by assigning a value to the *p in changeValue()
void changeValue(int *p)
{
*p = an int value;
}
void changeValue( int* ) ;
int main( void )
{
int i = 4; // Suppose i is stored at address 1000h
int * p;
p = &i; // Now p stores the address of i that is 1000h
changeValue(p); // Can also be written as changeValue(&i);
// Here you are passing the address of i to changeValue function
return 0 ;
}
void changeValue( int* p ) // Accept a parameter of type int*
{
*p = 100 ; // store the value 100 at address 1000h
return ;
}
int i = 4;
int * p = &i;
changeValue(p);
printf("%d",*p);
void changeValue(int *p)
{
*p = 5;
}
Full program - http://ideone.com/DCvhxE
If you dereference the pointer in changeValue and assign to it, it will alter the value of i in the calling frame.
e.g.:
void changeValue(int *p)
{
*p = 0;
}

Resources