1

From this tutorial website:

To declare an array in C, a programmer specifies the type of the elements and the number of elements required by an array as follows −

type arrayName [ arraySize ];

It seems this syntax declares the array and gives it space in memory, but it doesn't initialise any of the values.

This seems similar to the malloc command. Is the above notation a shorthand for malloc?

Connor
  • 867
  • 7
  • 18
  • 1
    `malloc` allocates memory in heap and needs to be freed explicitly. – Karthick Mar 09 '23 at 10:30
  • 3
    Tutorialspoint is an [infamously bad site](https://stackoverflow.com/questions/62816217/are-the-c-mock-tests-at-tutorialspoint-correct). You shouldn't learn C programming from people who don't know C programming. – Lundin Mar 09 '23 at 10:49
  • @Lundin Great advice! Where should I be looking? – Connor Mar 09 '23 at 11:02
  • 2
    stackoverflow.com :) – Lundin Mar 09 '23 at 11:56
  • @Connor https://kremlin.cc/k&r.pdf – August Karlstrom Mar 09 '23 at 12:08
  • @Lundin I will definitely keep asking questions! But is there any other website which is considered a good source of information on C? For example, I often struggle to find the headers that standard functions are included in! – Connor Mar 09 '23 at 13:24
  • 1
    @Connor For that kind of "look it up" questions [man](https://linux.die.net/man/) or the [C section](https://en.cppreference.com/w/c) of cppreference.com. – Lundin Mar 09 '23 at 14:36

4 Answers4

3

This seems similar to the malloc command. Is the above notation a shorthand for malloc?

No, it is not.

Depending on the storage duration not initialized objects will be:

  1. zeroed having static storage duration
  2. not initialized if they have automatic storage duration
type array_static_storage_duration [ arraySize ];

void foo(void)
{
     type array_automatic_storage_duration [ arraySize ];
     static type array_static_storage_duration1 [ arraySize ];
    
}

Automatic storage duration objects will stop existing when you exit the scope you have defined them.

Objects allocated using malloc have allocated storage duration and their lifetime is the same as the program (unless you free them)

From C standard:

An object whose identifier is declared with external or internal linkage, or with the storage-class specifier static has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration.

5 For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.) If the block is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration is reached in the execution of the block; otherwise, the value becomes indeterminate each time the declaration is reached.

6 For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.27) If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.

0___________
  • 60,014
  • 4
  • 34
  • 74
3

What's relevant here is the C concept of storage duration, which mainly tells how long a variable is guaranteed to remain valid, but also if/how a variable is default-initialized and under which conditions it holds an indeterminate value (essentially "garbage value").

  • Objects with static storage duration are guaranteed to be zero-initialized. All objects declared outside any function and/or as static have static storage duration. So in case the array in your example is declared outside any function, it is guaranteed to be zero-initialized.

  • Objects with automatic storage duration are not initialized unless the programmer did so explicitly. These are all variables declared at local scope, what we refer to as local variables. But also parameters to functions. In case the array in your example is declared inside a function, then it has automatic storage duration and the values it contain are indeterminate.

  • Objects with allocated storage duration are those explicitly created by the malloc family of functions. If they are initialized or not depends on which function that was used: malloc does not initialize the values but leave them indeterminate, calloc does initialize all values to zero.

So just as it happens, a variable with automatic storage duration has the same initialization rules as data with allocated storage duration returned from malloc. But that's about all those two variable types have in common.

The C language does not dictate where in memory something is stored. However in practice, heap allocation in C can probably be assumed to only happen when a function explicitly says it will. Apart from malloc family, there are also some non-standard ones like strdup and getline which explicitly document that they use heap allocation internally.

That being said, some implementations of for example stdio.h may use heap allocation internally - which is fine as far as the C standard cares. If they don't document it, they will also do the clean-up free() internally.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

No, the function malloc allocates memory at runtime from the free store (or heap). This memory can be accessed like an array but it is assigned to a pointer. This dynamically allocated "array" is typically used when we don't know in advance how large it needs to be. The memory also needs to be freed with the function free.

August Karlstrom
  • 10,773
  • 7
  • 38
  • 60
  • Do we also use `malloc` when we're passing the array as the return value? If so, what's the point in array declaration notation? It seems a lot less useful. – Connor Mar 09 '23 at 13:18
  • 1
    You can use the result from *malloc* as a return value but it is more idiomatic to write to an array passed to the function by the caller. Non-dynamic arrays have better performance since they are either statically allocated or stack allocated. Some programming languages (like Java if I'm not mistaken) use only heap allocated arrays behind the scenes. – August Karlstrom Mar 09 '23 at 13:54
  • Great! I've just stumbled onto a similar description to this in an MIT lecture! So, should I be passing stack referenced arrays into inner functions to make the process faster? – Connor Mar 09 '23 at 14:35
  • 1
    @Connor Yes, that is more efficient. It is also a good idea to pass the length of the array so the function know where it ends. – August Karlstrom Mar 10 '23 at 10:11
1

Is the above notation a shorthand for malloc?

No. When you declare an array as

T a[N];

what you get in memory looks something like this:

   +---+
a: |   | a[0]
   +---+ 
   |   | a[1]
   +---+ 
   |   | a[2]
   +---+
    ...

There is no object a apart from the array elements themselves. If declared locally to a function, like

void foo( void )
{
  T a[N];
  ...
}

the memory for the array will (usually) be taken from the same store as any other local variable. That memory will also be released when the function exits.

When you allocate memory as

T *a = malloc( sizeof *a * N );

what you get in memory looks like this:

   +---+         +---+
a: |   | ------> |   | a[0]
   +---+         +---+
                 |   | a[1]
                 +---+
                 |   | a[2]
                 +---+
                  ...

The pointer variable a is allocated like any normal variable, and once the function exits it is destroyed, but the memory allocated for the array elements is not - that memory remains allocated until you explicitly call free, so you either need to return that pointer to any calling function or free the memory before you exit the current function.

John Bode
  • 119,563
  • 19
  • 122
  • 198