0
#include <stdio.h>

int main(void) {
    for (int i = 0; i < 5; i++) {
        int arr[5] = {0};
        // arr gets zeroed at runtime, and on every loop iteration!
        printf("%d %d %d %d %d\n", arr[0], arr[1], arr[2], arr[3], arr[4]);
        // overwrite arr with non-zero crap!
        arr[0] = 3;
        arr[1] = 5;
        arr[2] = 2;
        arr[3] = 4;
        arr[4] = 1;
    }
    return 0;
}

Apparently this works:

> gcc -Wall -Wextra -pedantic -std=c99 -o test test.c;./test
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

But:

  • What's going on under the hood?
  • Is this guaranteed to work for arrays of any size?
  • Have I found the most elegant way of zeroing an array on every iteration of a loop?
  • To test the array content the loop is not really necessary anyway try to make the array a global variable (compiling in release) and see the results! ;) – Adriano Repetti May 14 '12 at 12:46
  • Yes, that's the point. With {0} you initialize the array, you do not reset its value! – Adriano Repetti May 14 '12 at 13:39
  • I think we're speaking about something different. Instead of the array imagine to have: "int value = 0". This is initialization and "value = 0" is reset. The {0} syntax for arrays is **standard** (and it works only if you want to initialize to 0) but you can't use it outside the declaration (so the loop itself is useless for testing/demo purposes). To read as: strip the loop because useless and the question is "what {0} does?" – Adriano Repetti May 14 '12 at 14:26
  • "works" by chance; you left `i` uninitialized in the `for`. – Jens May 14 '12 at 15:01
  • It's going to be a "@pub" discussion! I mean, for this example the loops is _irrelevant_ because you **declare and initialize** a new variable each time (coincidentally the compiler probably will reuse the same stack space). That's a syntax can be used to initialize arrays to zero (as pointed in linked posts). The loop could demonstrate something if you keep the variable outside the loop and you reset its content in the loop but it can't be done with that syntax. If you keep the declaration there then _loop scoped_ or _function scoped_ just demonstrate the initialization syntax. Anyway... – Adriano Repetti May 14 '12 at 15:27

6 Answers6

6

You are creating a new array at each iteration, so there is no re-initialization.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90
  • the compiler doesn't tell the processor... but yes it is possible that it uses the same region. In this case it is only because the stack pointer has the same address each time `arr` is created. – UmNyobe May 14 '12 at 13:11
  • In C allocating\deallocating on the stack is just made by arith. operations on `esp`, the stack pointer. It is very difficult to be faster. And "saying any worthy compiler" means that this behavior depends on compilers, which is false (assuming the same OS). – UmNyobe May 14 '12 at 13:40
3

See according to me whenever you are iterating over a loop, then whatever variables you are declaring inside the loop are local to that loop. So at the end of the loop they are getting destroyed, and when the loop is again starting then they are being created again. So, 1. answered above; 2. yes this should work for array of any size; 3. no...

Gaurav Bansal
  • 201
  • 2
  • 11
  • If this isn't the most elegant way to zero the array on every iteration, what do you consider to be a more elegant way to do it? – Jonathan Leffler May 14 '12 at 12:49
  • You have not found this method, this is the only easiest method, to do. my "no" was to the question that you have found this method. – Gaurav Bansal May 14 '12 at 12:54
  • 1
    I'd like to up-vote you; the other parts of your answer are good. But the 'No' defies my understanding of English and prevents me from up-voting. – Jonathan Leffler May 14 '12 at 13:03
3

The variable arr is created and initialized on every iteration of the loop because that's what you wrote. In your example, the code does something analogous to memset() to set the array to zero, but possibly more efficiently and inline. You could write a non-zero initializer too.

Yes, it works for 'any' size of array. If the arrays are bigger, the loop will be slower.

It is a very elegant way to achieve the effect. The compiler will do it as fast as possible. If you can write a function call that's quicker, the compiler writer's have goofed.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
3

This has been answered before:

What's going on under the hood?

The compiler will generate code equivalent to memset (see Strange assembly from array 0-initialization for full details).

Is this guaranteed to work for arrays of any size?

Up to the limit of your available stack size, yes.

Have I found the most elegant way of zeroing an array on every iteration of a loop?

I suppose so. :)

Community
  • 1
  • 1
gavinb
  • 19,278
  • 3
  • 45
  • 60
0

Yes, the C Standard guarantees that your array elememts are zeroed on each loop iteration. If you only want them zerored on the first iteration, make the array static, i.e. with

static int arr[5] = {0}; 

You may leave out the = { 0 } in this case, as static data is required to be initialized as if all elements were assigned 0 in the absence of an initializer (or NULL for pointers, or 0.0 for floating point values, recursively for structs).

Note also, that if you use less initializers than the array dimension specifies, the remaining elements are assigned zeros. So

int arr[5] = {42, 0xdead};

is equivalent to

int arr[5] = {42, 0xdead, 0, 0, 0};

and using a single 0 is just a special case of this rule.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • Strictly, the static means 'if you only want them zeroed when the program is started'. They'd not be zeroed on any entry to the loop; they would be zero on the very first entry to the loop. – Jonathan Leffler May 14 '12 at 12:51
  • @JonathanLeffler ... but since the declaration is inside the loop's scope, the variable really doesn't exist outside the scope, does it? – unwind May 14 '12 at 12:52
  • @unwind: if the variable is marked `static` in the loop, it has a storage duration such that it exists (storage is allocated and initialized for it) from program startup to exit; it is simply not accessible except from within the body of the loop. If, as in the question, it is an automatic variable, then there is no storage allocation except when the loop is executing. – Jonathan Leffler May 14 '12 at 12:55
  • @JonathanLeffler: Yeah, I know. I was being somewhat tongue-in-cheek, since it can be argued that whether or not a variable is zeroed or not when it's not accessible in any way can be considered a bit moot. But, of course, under the abstraction provided by scopes what you're describing is exactly what's going on. Well put. – unwind May 14 '12 at 13:12
-2

Not ignoring the logical error of the code (re initialization at each iteration) I will recommend using memcpy or memset whenever you want to assign all the elements of an array.. This is the tried and tested way, which fortunately works as a charm in almost all the compiler implementations.

Memset Example

MemCpy Example

So, Using Memset your code will become;;

int a[5]; 
memset(a,0,<number of bytes to be set to> sizeof(int)*5); 

Please read the documentation to find out why it is fast, you will enjoy...

EDIT Sorry and Thanks for all the down voters / commentors... I corrected the answer...

Amit
  • 13,134
  • 17
  • 77
  • 148
  • 1
    Which compilers are you thinking of? Are they still supported? The C99 standard at least requires that it be supported. I have some niggling doubts about what C89 mandated; there were some limitations there, IIRC. – Jonathan Leffler May 14 '12 at 12:58
  • 2
    A compiler for which the above code doesn't work is seriously broken. `int a[5] = {0};` is guaranteed by the standard to initialise all array elements to 0. – Daniel Fischer May 14 '12 at 12:59
  • -1 This does not work. `memset` needs the size in octets, and 5 ints are more than 5 octets. And your assertion that this works only for lucky people is wrong as well. It's guaranteed to work by the C language standard. – Jens May 14 '12 at 13:06
  • int a[5] = {0} never worked during my college practicals... we were struggling with Borland C++ compiler (Turbo C).... Any ways I tried it on VC, and gcc, g++ and it seems working now... So I corrected my answer... Will test on Tubro C++ as well soon and let you guys tell the results... – Amit May 14 '12 at 13:16
  • Right - Turbo C is an incredibly archaic compiler, and is limited to (at best) strict C89. But only a very sadistic course would have made you use it at any time in the last decade or so. But, interestingly, it appears that you can download Turbo C 2.01 (from circa 1989), and also Turbo C++ 5.5 (from considerably more recently). See Wikipedia and Embarcadero (courtesy of Google). – Jonathan Leffler May 14 '12 at 13:26
  • @JonathanLeffler, Unfortunately we had Turbo C to struggle with.. Will you beleive we wrote Java/ JSP code inside notepad (not even notepad++)... I think it was the drawback of the system... Anyways thanks for correcting me.... I will remember that!! – Amit May 14 '12 at 13:30
  • Why is initializing the array on each loop iteration a logical error? If the array is declared inside the loop, then it needs to be initialized inside the loop (but not necessarily to zeros). Whether or not creating a fresh, new array on each loop iteration is a logical error would depend entirely on the requirements of the algorithm being implemented. – Michael Burr May 14 '12 at 14:48
  • "If the array is declared inside the loop, then it needs to be initialized inside the loop (but not necessarily to zeros)." But in IMHO declaring array every time loop starts (and than subsequently assigning it to same value every time) itself is a bad program design, until you have no other option .. – Amit May 15 '12 at 04:49