5

I have a struct defined in this way.

typedef struct COUNTRY {
    char Code[3];
    char Country[30];
    int Population;
    float Expectancy;
    struct Country *Pointer;
} COUNTRY;

I have seen an array of structs allocated like this:

COUNTRY *countries = calloc(128, sizeof(COUNTRY));

or maybe like this:

COUNTRY *countries = malloc(128 * sizeof(COUNTRY));

But what does this do:

COUNTRY countries[128] = {};

Because I am still able to write to each entries' fields in all cases. Is the third option just bad form? It seems better to me because you can put that line up with the rest of your variable declarations outside of main(). Otherwise, you can only calloc() or malloc() inside of main() or other function.

Am I doing something wrong?

chrissphinx
  • 364
  • 3
  • 14

5 Answers5

6

This:

COUNTRY countries[128];

simply defines an object whose type is "array of 128 COUNTRY elements".

The = {} is an initializer -- but empty initializers are illegal in C (I think gcc supports them as an extension). A portable alternative is:

COUNTRY countries[128] = { 0 };

which initializes all members of all elements to zero (0 for integers, \0' for characters, 0.0 for floating-point, NULL for pointers, and recursively for sub-elements). But since you specified the number of elements in the array (as 128), the initializer has no effect on how the array object is allocated.

If the declaration occurs inside a function definition, the array object has automatic storage duration, which means that it ceases to exist when execution reaches the end of the enclosing block. Such objects are commonly allocated on "the stack".

If it occurs outside any function definition (at file scope) or if it has the keyword static, then it has static storage duration, which means that it continues to exist for the entire execution of the program.

Objects allocated with malloc or calloc have allocated storage duration, which means that they continue to exist until they're explicitly deallocated by a call to free(). Such objects are commonly allocated on "the heap". (I'm ignoring realloc(), which complicates the description a bit.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
3

The first two statements will allocate array of structs on the heap, while the last one will initialize the array of structs on the stack.

It is not a bad form, it is just a matter where you want your data to be stored - on the stack ( freed automatically when your variable goes out of the scope, stack usually have significantly smaller size then heap, so you could overflow it if you place big data structures there), or on the heap (lifetime of data is not related to the scope, you need to manually free your memory).

It seems better to me because you can put that line up with the rest of your variable declarations outside of main().

If you need statically allocated object with the lifetime of the program, use this approach, there's nothing wrong with it. Please note that in this particular case, variable is not stored on the stack, but in the .data segment of your program (check this question for more details: How are global variables stored?).

Community
  • 1
  • 1
Nemanja Boric
  • 21,627
  • 6
  • 67
  • 91
  • In addition to lifetime differences, on many systems stack size is much smaller than heap size, so many people tend to avoid allocating large arrays on the stack. – Laurence Gonsalves Sep 19 '13 at 18:03
0

The last form is 'stack allocated' or 'statically allocated'. Like calloc, all of the fields will be zeroed out.

Inside a function it is 'stack allocated' and that memory will go away when the function returns.

Outside any function, at file scope, it is statically allocated and a global piece of memory allocated before main() starts.

bolson
  • 44
  • 2
0

malloc/calloc are used when you don't know how many you need at compile time. For example in a linked list, you need to allocate/deallocate nodes on the fly. When you use an array, you the know exactly how many you need at compile time.

What also differs is where the memory is taken from. If you declare an array in a function, the memory will be taken from the stack. In the case of malloc/calloc, the memory is set aside in the heap.

Freddie
  • 871
  • 6
  • 10
0

= {};

is GNU C extension and is the same as:

= {0};

ouah
  • 142,963
  • 15
  • 272
  • 331