60569

Why is my initialization function returning null?

Question:

I'm writing a program in C for the first time. I have a good bit of experience with C++, but C's reliance on pointers and the absence of new and delete are really throwing me off. I defined a simple data structure, and wrote a function that will initialize it (by taking a pointer). Here's my code:

//in Foo.h #include <stdio.h> #include <stdlib.h> typedef struct Foo { struct Foo * members[25] ; } Foo ; void foo_init(Foo * f) ; void foo_destroy(Foo * f) ; //in Foo.c void foo_init(Foo * f) { f = (Foo*)malloc(sizeof(Foo)); for (size_t i = 0 ; i < 25 ; i++) { f->members[i] = NULL ; } } //define foo_destroy() //in main.c #include "Foo.h" int main(int argc, const char * argv[]) { Foo * f ; foo_init(f) ; /* why is f still NULL here? */ foo_destroy(f) ; /* ... */ return 0; }

When I tested my foo_init() function on f (pointer to a Foo struct), it was null after the function returned. The pointer f <em>inside</em> foo_init() is initialized just fine, however, so I don't think this is a problem with the init function itself. Shot in the dark, but could this be related to the way C handles passing by value/passing by reference (something I still don't entirely have a grasp on)? How can I correct this?

Answer1:

void foo_init(Foo* f)

In C parameters are passed by value. Here you pass a parameter named f, of type Foo*. In the function you assign to f. But since the parameter is passed by value, you are assigning to the local copy, private to that function.

In order for the caller to see the newly allocated struct, you need an extra level of indirection:

void foo_init(Foo** f) { *f = ...; }

And at the call site:

Foo* f; foo_init(&f);

Now, since your function is designed to send a new value to the caller, and your function currently has void return value, it would make more sense to return the new value to the caller. Like this:

Foo* foo_init(void) { Foo* foo = ...; return foo; }

You would call this like so:

Foo* f = foo_init();

Answer2:

1) You go out of bounds in your for-loop, (as pointed out by @user3121023 change to 25)

2) You are (m)allocating space for a local variable, use:

Foo *foo_init(void) { Foo *f = malloc(sizeof(Foo)); /* don't cast malloc */ for (size_t i = 0 ; i < 25 ; i++) { f->members[i] = NULL ; } return f; }

and in main:

f = foo_init();

Answer3:

In function void foo_init(Foo * f) you are passing a pointer. Now this pointer is passed as value in this function and modifications to this variable inside the function will not be reflected outside this function. In other words the variable f in function foo_init is a local variable.

so you should return the value of f by doing:

Foo* foo_init(Foo * f) { f = (Foo*)malloc(sizeof(Foo)); for (size_t i = 0 ; i < 25 ; i++) { f->members[i] = NULL ; } return f; }

Apart from this note that I have changed the condition in for loop. You have allocated array of 25 objects. So your for loop should go from 0 to 24.

and in main you should

f = foo_init();

Recommend

  • Linked List head not being updated across function calls
  • Conflicting Types Error
  • C++/C# Float issues
  • unexpected result iterating over a boost::python vector_indexing_suite
  • Can we reuse allocated memory
  • CGAL: How to efficiently calculate the area of facets of a polyhedron?
  • Salted sha512 in C, cannot synchronise with Symfony2's FOSUserBundle
  • Passing C# structure with string array to c++ function which accepts void * for c# structure and cha
  • Getting segmentation fault while using malloc
  • How to get from a tuple to a tuple of references to elements in the tuple?
  • Doxygen and typedefs inside namespaces
  • Linked list in C, no member error
  • Passing unspecialized template as a template parameter
  • OSStatus error -50 (invalid parameters) AudioQueueNewInput recording audio on iOS
  • iOS - Is this a task for enums?
  • How to work with AMMediaType for video filters
  • HALF_PTR Windows data type
  • why my app based on boost::asio didn't accept new connection
  • NSMutableArray instance used in a block
  • Is there a parser equivalent of 'fragment' marking in ANTLR4?
  • sweetalert2 inputoptions from file in select example
  • How to unpack 32bit integer packed in a QByteArray?
  • C++ Single function pointer for all template instances
  • Simple linked list-C
  • Sencha Touch 2.0 Controller refs attribute not working?
  • why overloaded new operator is calling constructor even I am using malloc inside overloading functio
  • When to use `image` and when to use `Matrix` in Emgu CV?
  • Why is the size of this struct 32?
  • What is the “return” in scheme?
  • How to make a tree having multiple type of nodes and each node can have multiple child nodes in java
  • output of program is not same as passed argument
  • Which linear programming package should I use for high numbers of constraints and “warm starts” [clo
  • Akka Routing: Reply's send to router ends up as dead letters
  • Linker errors when using intrinsic function via function pointer
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • json Serialization in asp
  • LevelDB C iterator
  • unknown Exception android
  • Checking variable from a different class in C#
  • How can i traverse a binary tree from right to left in java?