Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialising arrays in C++

Everywhere I look there are people who argue vociferously that uninitialised variables are bad and I certainly agree and understand why - however; my question is, are there occasions when you would not want to do this?

For example, take the code:

char arrBuffer[1024] = { '\0' };

Does NULLing the entire array create a performance impact over using the array without initialising it?

like image 540
Konrad Avatar asked Nov 20 '09 12:11

Konrad


People also ask

What is initializing an array?

The process of assigning values to the array elements is called array initialization. Once an array is declared, its elements must be initialized before they can be used in the program. If they are not properly initialized the program produces unexpected results.

Does C initialize arrays to 0?

Initialize Arrays in C/C++ c. The array will be initialized to 0 if we provide the empty initializer list or just specify 0 in the initializer list.

How do you initialize an array of arrays?

To initialize an array of arrays, you can use new keyword with the size specified for the number of arrays inside the outer array. int[][] numbers = new int[3][]; specifies that numbers is an array of arrays that store integers.


4 Answers

I assume a stack initialization because static arrays are auto-initialized.
G++ output

   char whatever[2567] = {'\0'};
   8048530:       8d 95 f5 f5 ff ff       lea    -0xa0b(%ebp),%edx
   8048536:       b8 07 0a 00 00          mov    $0xa07,%eax
   804853b:       89 44 24 08             mov    %eax,0x8(%esp)
   804853f:       c7 44 24 04 00 00 00    movl   $0x0,0x4(%esp)
   8048546:       00 
   8048547:       89 14 24                mov    %edx,(%esp)
   804854a:       e8 b9 fe ff ff          call   8048408 <memset@plt>

So, you initialize with {'\0'} and a call to memset is done, so yes, you have a performance hit.

like image 86
Arkaitz Jimenez Avatar answered Oct 21 '22 11:10

Arkaitz Jimenez


If the variable is a global or static, then its data is typically stored verbatim in the compiled executable. So, your char arrBuffer[1024] will increase executable size by 1024 bytes. Initializing it will ensure the executable contains your data instead of the default 0's or whatever the compiler chooses. When the program starts, no processing is required to initialize the variables.

On the other hand, variables on the stack, such as non-static local function variables, are not stored in the executable the same way. Instead, on function entry the space is allocated on the stack and a memcpy places the data into the variable, thereby impacting performance.

like image 36
spoulson Avatar answered Oct 21 '22 11:10

spoulson


The rule is that variables should be set before they're used.

You do not have to explicitly initialize them on creation if you know you will be setting them elsewhere before use.

For example, the following code is perfectly okay:

int main (void) {
    int a[1000];
    : :
    for (int i =0; i < sizeof(a)/sizeof(*a); i++)
        a[i] = i;
    : :
    // Now use a[whatever] here.
    : :
    return 0;
}

In that case, it's wasteful to initialize the array at the point of its creation.

As to whether there's a performance penalty, it depends partially on where your variable is defined and partially on the execution environment.

The C standard guarantees that variables defined with static storage duration (either at file level or as statics in a function) are first initialized to a bit pattern of all zeros, then set to their respective initialized values.

It does not mandate how that second step is done. A typical way is to just have the compiler itself create the initialized variable and place it in the executable so that it's initialized by virtue of the fact that the executable is loaded. This will have no performance impact (for initialization, obviously it will have some impact for program load).

Of course, an implementation may wish to save space in the executable and initialize those variables with code (before main is called). This will have a performance impact but it's likely to be minuscule.

As to those variables with automatic storage duration (local variables and such), they're never implicitly initialized unless you assign something to them, so there will also be a performance penalty for that. By "never implicitly initialized", I mean the code segment:

void x(void) {
    int x[1000];
    ...
}

will result in x[] having indeterminate values. But since:

void x(void) {
    int x[1000] = {0};
}

may simply result in a 1000-integer memcpy-type operation (more likely memset for that case), this will likely to be fast as well. You just need to keep in mind that the initialization will happen every time that function is called.

like image 21
paxdiablo Avatar answered Oct 21 '22 11:10

paxdiablo


Measure!

#include <stdio.h>
#include <time.h>

int main(void) {
  clock_t t0;
  int k;

  t0 = clock();
  for (k=0; k<1000000; k++) {
    int a[1000];
    a[420] = 420;
  }
  printf("Without init: %f secs\n", (double)(clock() - t0) / CLOCKS_PER_SEC);

  t0 = clock();
  for (k=0; k<1000000; k++) {
    int a[1000] = {0};
    a[420] = 420;
  }
  printf("   With init: %f secs\n", (double)(clock() - t0) / CLOCKS_PER_SEC);

  return 0;
}
$ gcc measure.c
$ ./a.out
Without init: 0.000000 secs
   With init: 0.280000 secs
$ gcc -O2 measure.c
$ ./a.out
Without init: 0.000000 secs
   With init: 0.000000 secs
like image 38
pmg Avatar answered Oct 21 '22 11:10

pmg