A forum user recently posted an unusual construction that compiles, and runs, so I've been scratching my head about what the compiler actually does with it. I have not gone so far as to look at the machine language generated.
Here is a simplified test case. Challenge: correctly guess what is printed, before running it!
void setup() {
Serial.begin(9600);
for (int j = 1; j < 5; j++) {
Serial.print(j);
Serial.print(" : ");
int r[j] = {j * 2}; //the "unusual construction"
Serial.println(r[j]);
}
}
void loop() {}
Obviously (or not) this crashes if j loops from 0 instead of 1.
When j = 1;
create an array: r[1] = {2};
print(r[1]) -> out of bound access.
...
Oops, I added the print statement and forgot about the upper bound.
For a list of array initializer, if the list is smaller than the explicit size, the rest will be set to 0.
print(r[1]) -> out of bound access.
That should just print garbage, probably get a warning though.
Don't know C++, but C is not going to be very happy declaring an array with variable length, int r[j] = {j * 2};
arduino_new:
For a list of array initializer, if the list is smaller than the explicit size, the rest will be set to 0.
Not for a locally declared array, initialization is un-specified.
DKWatson:
Not for a locally declared array, initialization is un-specified.
hmm. Why would it be different. Aren't global and local declaration the same in the code generation phase?
Local declaration will be done on the stack with [0] at the current SP. No knowledge of contents, Global, yes, all will be 0.
Use code tags Watson!!!
That should have come out
Local declaration will be done on the stack with [0] at the current SP. No knowledge of contents, Global, yes, all will be 0.
DKWatson:
Use code tags Watson!!!
That should have come out
Local declaration will be done on the stack with [0] at the current SP. No knowledge of contents, Global, yes, all will be 0.
Can you link to the quote?
This piece of code produce the following result:
#include <stdio.h>
int main()
{
int arr[10] = {1} ;
for (int i=0; i<10; i++) {
printf("Address: %p\tValue: %d\n", arr+i, arr[i]);
}
return 0;
}
Address: 0028fee4 Value: 1
Address: 0028fee8 Value: 0
Address: 0028feec Value: 0
Address: 0028fef0 Value: 0
Address: 0028fef4 Value: 0
Address: 0028fef8 Value: 0
Address: 0028fefc Value: 0
Address: 0028ff00 Value: 0
Address: 0028ff04 Value: 0
Address: 0028ff08 Value: 0
Process returned 0 (0x0) execution time : 0.019 s
Press any key to continue.
And when I omit the initializer, it produces garbage as expected.
int arr[10];
Address: 0028fee4 Value: -904843762
Address: 0028fee8 Value: -2
Address: 0028feec Value: 1958494522
Address: 0028fef0 Value: 1958495693
Address: 0028fef4 Value: 4200656
Address: 0028fef8 Value: 2686868
Address: 0028fefc Value: 4200750
Address: 0028ff00 Value: 4200656
Address: 0028ff04 Value: 79
Address: 0028ff08 Value: 8
Process returned 0 (0x0) execution time : 0.029 s
Press any key to continue.
Code tested with CodeBlock which uses standard gcc compiler.
That is the point. Better explained by you than me. Apparently since C99, default initialization will set all members to 0 or NULL. Declaration as global or static will do the same. Declaration in a function (local) without initialization is undefined.
This, from 21st Century C:
"Initialize Arrays and Structs with Zeros
If you declare a variable inside a function, then C won’t zero it out automatically
(which is perhaps odd for things called automatic variables). I’m guessing that the
rationale here is a speed savings: when setting up the frame for a function, zeroing
out bits is extra time spent, which could potentially add up if you call the function a
million times and it’s 1985.
But here in the present, leaving a variable undefined is asking for trouble.
For simple numeric data, set it to zero on the line where you declare the variable. For
pointers, including strings, set it to NULL."
In fact declaring int array[n] = {}; is enough to initialize to zeros.
Your statement in #3 is correct.