5

I'm reading C How to Program and I have a question about storage classes of arrays. In the book it says:

Array and structs are "static" entities in that they remain the same size throughout the program execution (they may, of course, be of automatic storage class and hence created and destroyed each time the blocks in which they're defined are entered and exited)

I'm not sure about what blocks mean, my current understanding is that function/for/while are blocks. I've tried the following:

...
for (size_t i=1; i<=2; i++) {
    printf("round %c:", i+'0');
    int a[10];
    show_array(a, 10); // this is a function that prints all elements of `a`.
    for (size_t j=0;j<10;j++) {
        a[j]=8;
    }
}

I got the output:

round 1:0,0,0,0,-1160480784,22023,-1160481168,22023,1594487680,32766,
round 2:8,8,8,8,8,8,8,8,8,8,

It seems like int a[10] is static, and not automatic storage class, am I missing something? (I understand the four storage classes)

I used ideone.com to run my test, if you need this information.

15
  • 1
    What do you think "automatic storage class" means? Commented Nov 19, 2018 at 20:18
  • 1
    Are 32766 or -1160481168 "unitialised values"? If they are, why 8 isn't? Commented Nov 19, 2018 at 20:30
  • 2
    We have very good evidence that the array does not have static storage duration—anything with static storage duration is initialized to 0 at the start of the program, unless you initialize it to something else. Since your array contains garbage numbers like -1160480784, it cannot have static storage duration (unless your program has memory errors somewhere else). Commented Nov 19, 2018 at 20:30
  • 1
    Per C 2018 6.8.2 2, a compound statement is a block. A compound statement is a pair of braces, { and }, with declarations and/or statements inside it. Commented Nov 19, 2018 at 20:30
  • 1
    @user7813604: When execution of a block ends, the lifetime of each object with automatic storage duration associated with that block ends. When another execution of the block begins, each such object created in it has a new lifetime. Every iteration is different. Commented Nov 19, 2018 at 22:37

5 Answers 5

5

You are indeed missing something. a does have automatic storage, and the values that are printed are a consequence of the memory being re-used, not of the storage being persistent. The values will be reset in debug mode (perhaps not by all development environments, but some will set the members to 0xCCCCCCCC on each iteration). Also, good compilers (most compilers, if you enable all warnings) will tell you that you're using uninitialized data here.

If you still don't believe me, try this example. It will show that the memory values in a are overwritten by the values stored in b. The array a ceases to exist at the end of the if statement's dependent block of code, and all of that memory is made available to the system. On the next iteration, it will probably be used for array b, which is why you'll see values of 8 printed in array b, even though they were assigned to a.

for (size_t i=1; i<=2; i++)
{
    if( i&1 )
    {
        printf("round %c:", i+'0');
        int a[10];
        show_array(a, 10);
        for (size_t j=0;j<10;j++) a[j]=8;
    }
    else
    {
        printf("round %c:", i+'0');
        int b[10];
        show_array(b, 10);
        for (size_t j=0;j<10;j++) b[j]=888;
    }
}

For a final confirmation that memory is being re-used, you could modify show_array to print the raw pointer passed in, not just the individual elements. You should see the same address each time.

Sign up to request clarification or add additional context in comments.

5 Comments

Is that when the array a be automatic storage, it mean the array itself is automatic or the elements in the array be automatic?
An array has the same storage class as the elements inside it (how would an element inside an array outlive the array?)
What @DietrichEpp said. I'll add anote to the answer
@DietrichEpp: oh I got it!
Thank you sir I do believe you but it's just my style of asking.
4

"Automatic storage class" refers to the scope in which the variable is defined. It means that the memory allocated to the variable will be freed upon exiting the scope in which the variable was created, not that the memory will be initialized for you. You still have to do that yourself. The reason you see the 8s in the second iteration of your loop is because the same memory that was freed in the previous iteration was reassigned to the array.

Comments

3

The array a is an automatic variable because it is defined in a block scope, the block in this case being the body of the for loop. The fact that you see the values you set the last time doesn't mean the variable is static.

Automatic variables are uninitialized if not explicitly initialized. This basically means they'll contain whatever happened to be in those memory locations the last time they were used.

On the first iteration of the loop, you see seemingly random values in the array. The variable then goes out of scope at the end of the loop, and on the next iteration a new instance is created, but in this case it happened to be created at the same memory location it was created at last time, and nothing else happened to write to that memory location, so you end up seeing the same values. There's no guarantee that you'll see the same behavior if you for example make an unrelated code change or compile with different optimization settings.

Comments

2

When the lifetime of an object with automatic storage duration ends, that just means the memory is released (so that it may be used for other purposes). It does not guarantee that the memory is erased or that it is used for other purposes.

When the lifetime of another instance of the same object begins, memory is allocated for it again. It may happen to be the same memory that was used for it before. There is no guarantee that it was erased or used for other purposes.

Comments

2

Your program has what is scientifically known as undefined behaviour. In your case it results from using (printing) a bunch of int objects before initialising them.

Since the behaviour is undefined, program output can be anything at all, including a stream of characters that could possibly in theory lead someone into believing in an obvious nonsense (like a having static storage duration).

In practical terms, this is what happens if you ignore the high-brow world of language standards and look at the iron:

  • At round 1 a contains garbage values, remnants of whatever has been stored at that memory location previously.
  • At round 2 a still contains garbage values, remnants of whatever has been stored at that memory location previously.

The only difference is that the garbage looks familiar to you, because it happens to be your garbage. You can see it because the garbage people did not have a chance to collect it yet. It is still garbage however — the garbage people will remove it at some point.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.