Reputation: 107
Let's say I have a struct that is a list such as
typedef struct mylist {
int head;
int tail;
int size;
buckets_t *bucketslots;
} mylist_t;
and then
void create_list(mylist_t* list, int size) {
list->head = 0;
list->tail = 0;
list->size = size;
list->bucketslots = malloc(sizeof(bucket_t) * size);
}
Now, in my main method, if I perform:
mylist_t list1;
create_list(&list1, 1000);
Does the second to last line automatically malloc space for list1? Or, do I need to explicitly malloc space through
malloc(sizeof(mylist_t))
?
What I'd like to really know is if this is a valid procedure to make a struct of type mylist and start using it in main.
EDIT
It appears that C puts list1 on the stack when I declare the second to last line, but it does not go on the heap. If I want it on the heap, should I do the following? :
mylist_t* create_list(int size) {
mylist_t list1 = malloc(sizeof(mylist_t));
list->head = 0;
list->tail = 0;
list->size = size;
list->bucketslots = malloc(sizeof(bucket_t) * size);
return list1;
}
And then for calling the function:
create_list(1000);
With this, will I have access to list1 throughout the program?
Upvotes: 1
Views: 1349
Reputation: 965
Two things you need to understand.
When you declare a variable within any function or even within a chain-bracket statement block, that variable has no existence outside that block of code. You can use it as a parameter to other function calls, but if you try to reference it outside the statement block it is declared in, it is an error. These are local variables.
Variable declared inside a function are within the scope of that function only.
Global variables. You can declare a variable outside of any statement blocks or functions. It is global insofar as any function inside the same file can reference that variable.
Typically a compiler would allocate space for a local variable on the stack, although in practice a local variable might be kept in a register and never even stored in memory. These are details we leave to the compiler to sort out.
Sometimes people confuse "static" variables with "global variables". Static variables will not be "visible" by name outside the file you declare them in. Global variables can be visible, although you also need to declare them in a header file as "extern" to allow this.
One thing to note in C is that inside a chain bracket statement block you can reuse variable names declared outside the block. The one that is declared in the level closest to one you're at is the one that takes precedence.
In C this is perfectly valid and all the following variables are different :
void myfunc( int n )
{
if( n == 1 )
{
int n = 35 ;
/* This will print 35 */
printf( "n = %d\n", n ) ;
}
else
{
int n = 45 ;
/* This n variable has a value of 45 */
printf( "n = %d\n", n ) ;
}
/* but no matter what we did inside the if statements
* the n variable at this stage refers to the original one !
*
* So this printf will show the original value.
*/
printf( "n = %d\n", n ) ;
}
I mention this because an increasing number of programmers start on Java, where this would be illegal ( alas ) and find it confusing. It is extremely useful, especially in macros.
Upvotes: 0
Reputation: 145317
Your proposed alternative for create_list
to allocate and initialize a structure is almost correct:
list1
should be defined as a pointer to mylist_t
,bucket_t
instead of the size for the structure bucket_t
,Here is a modified version:
mylist_t *create_list(int size) {
mylist_t *list1 = malloc(sizeof(mylist_t));
list->head = 0;
list->tail = 0;
list->size = size;
list->bucketslots = malloc(sizeof(bucket_t*) * size);
for (int i = 0; i < size; i++)
list->bucketslots[i] = NULL;
return list1;
}
Upvotes: 1
Reputation: 84652
Does the second to last line automatically malloc space for list1?
No. Generally a list is created by allocating space for a node, and then allocating space as required for each additional node added to the list. (regardless of whether the space is allocated dynamically or not)
create_list(&list1, 1000);
initializes head
, tail
and size
values for list1
(a node of type mylist_t
) and then dynamically allocates an array of type buckets_t
with size
elements for that node. If that is the entirety of your list1
, then your list1
is allocated.
Upvotes: 1
Reputation: 36067
when you write
mylist_t list1;
create_list(&list1, 1000);
list1
is allocated on the stack, the struct contains a pointer. the members in the struct1 are not initialized.
the create_list
function will allocate space for the pointer to point to and initialize the struct in general
heap always need to be explicitly allocated with malloc/calloc. stack on the other hand is automatic.
Upvotes: 4
Reputation: 62179
C will never implicitly malloc()
anything.
In general, whenever you have a question of this sort, (until you become proficient enough with the language so as to stop even having questions of this sort,) remember that the philosophy of C is to never do anything behind your back, never do anything that you did not explicitly ask for.
Especially things that are not even part of the language, like memory allocation. In C, memory allocation is exclusively an issue of the runtime library. The language has no built-in knowledge of the concept of memory allocation.
Upvotes: 3