Static variable initialisation

Hi,

Having read the reference at https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/static/ I still unsure of static variable initialisation.

The text mentions that the variable is initialised once at the first call of the function.

My first question is: are statics function or block local?

The example code then shows the declaration of a static but not the initialisation. It begs the obvious questions:

Do statics get an a default value if not initialised?
If not then must initialisation occur at declaration so as to only occur once? Eg static int place = 0;

All in all the documentation and example code are pretty poor for this topic. If someone could answer these questions for me I’ll update the doco.

Thanks,
Scott

To my knowledge, they are block local.

I'm not sure about penalties assigning a constant value. I think that your example is just initialised once (similar to global variables).

static int  place = 0;

Something like below comes with a penalty in both memory usage and cpu cycles.

static in place = digitalRead(somePin);

See url=http://forum.arduino.cc/index.php?topic=413669.0

PS
This is not an "installation and troubleshooting" question :wink: It's far more a programming question and have reported your post so it can be moved to the appropriate section.

Thanks,

I really wish documenters would use the right words. It's so easy. If variables have block scope then the documentation should say so. (ie, not function scope).

I'm pretty sure that:

{
  static int  place = 0;
}

is not a constant, in so far as the declaration and initialisation occur once (at least that's how I understand static.

Why would your example of:

{
  static in place = digitalRead(somePin);
}

have a memory and cpu penalty? That would mean I'm wrong when I understand the declaration and initialisation of statics to occur only once.

Also from further reading (at least in C) static variables are initialised as 0 if not done so explicitly.

Just a tidbit: AFAIK the initialisation of a static to a function call return can't be done in C (but in C++ it can).

Thread moved.

Thanks.

is not a constant, in so far as the declaration and initialisation occur once (at least that's how I understand static.

Zero is a constant value :wink:

Why would your example of ... have a memory and cpu penalty? That would mean I'm wrong when I understand the declaration and initialisation of statics to occur only once.

Read the thread that I linked.

Initialisation of variables is a two step process where the second step is optional.

From the days that I coded MCS51 based processors in assembly, the first step is to clear all the memory to 0. In C/C++, the same happens and it's done before the C/C++ main() function is called.

Next the global and static variables are initialised if their values are not set to 0. E.g.

int x = 5;  // requires extra step to initialise to 5
int z;      // does not require an extra step

void setup()
{
  Serial.begin(57600);
}

void loop()
{
  static int y = 334;       // requires an extra step to initialise to 334
  Serial.println(x++);
  Serial.println(y++);
  Serial.println(z++);
}

I do not know where this step happens; somebody else might be able to give the exact details; I can't find it back in the list file.

You can compile without assigning values and with assigning values and check the difference in size (code / ram); be aware that you have to use the variables (e.g. print them as in the example) or the optimisation process will throw them away.

Using my example with the digitalRead(), the second step is done when the function is called the first time.

If you have a code like
[code]
void yourFunc()
{

  static int x = digitalRead(yourPin);

  ...
  ...
}

The resulting (equivalent C/C++) code around it looks like below (slightly simpler to understand than the assembly that is generated).

bool xIsInitialised = false;

void setup()
{
  ...
  ...
}

void loop()
{
  yourFunc();

  ...
  ...
}

void yourFunc()
{

  static int x;

  if(xIsInitialised == false)
  {
    x = digitalRead(yourPin);
    xIsInitialised = true;
  }

  ...
  ...
}

So the variable is only initialised once with the result of digitalRead(). As can be seen, the penalty is in the extra flag (RAM) and the code around it (flash, CPU cycles).

sterretje:
Initialisation of variables is a two step process where the second step is optional.

Three steps for globals*: the BSS section is cleared / set to zero; the DATA section is copied from Flash; run-time determined values are initialized by snippets of code in an initN section.

BSS contains global variables with no initial value or a zero initial value.

DATA contains global variables that have static non-zero values. An example...

int AnIntOfFive = 5;

The 0x0005 can be copied as-is from Flash so that is how AnIntOfFive is initialized.

A run-time determined example...

bool BigRedButton = digitalRead(7);

The only way to initialize BigRedButton is to call digitalRead. With that definition, a snippet of code is placed in an initN section that calls digitalRead then stores the result in BigRedButton.

The initN sections are run before main is called.

(Technical note: All the initialization is performed in various initN sections. I just cannot remember which ones do what. The description above would be incomprehensible if I had tried to include that detailed. For example, there is an initN section that clears the BSS section and there is a different initN section that copies DATA from Flash.)

The fourth initialization (static locals with run-time value) is performed exactly as you described.

  • I suspect simple static locals (zero / constant value) are initialized with globals.

I took the below extremely simple example to see how the variable is initialised

void setup()
{
  Serial.begin(57600);
}

void loop()
{
  static int xyz = 5;
  Serial.println(xyz++);
}

And after compiling I ran “c:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objdump.exe” -S -h topic_576489.0.ino.elf > topic_576489.0.ino.2.elf.lst.

I can find the data section back in the beginning of the lst file

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         00000018  00800100  000006d6  0000076a  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         000006d6  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          000000a6  00800118  00800118  00000782  2**0
                  ALLOC
  3 .comment      00000011  00000000  00000000  00000782  2**0
                  CONTENTS, READONLY

...
...

I also found the code that does the initialisation. First the static (and possibly global variables) that need initialisation with a value different from 0.

00000076 <__do_copy_data>:
  76:	11 e0       	ldi	r17, 0x01	; 1
  78:	a0 e0       	ldi	r26, 0x00	; 0
  7a:	b1 e0       	ldi	r27, 0x01	; 1
  7c:	e6 ed       	ldi	r30, 0xD6	; 214
  7e:	f6 e0       	ldi	r31, 0x06	; 6
  80:	02 c0       	rjmp	.+4      	; 0x86 <__do_copy_data+0x10>
  82:	05 90       	lpm	r0, Z+
  84:	0d 92       	st	X+, r0
  86:	a8 31       	cpi	r26, 0x18	; 24
  88:	b1 07       	cpc	r27, r17
  8a:	d9 f7       	brne	.-10     	; 0x82 <__do_copy_data+0xc>

And for the bss

0000008c <__do_clear_bss>:
  8c:	21 e0       	ldi	r18, 0x01	; 1
  8e:	a8 e1       	ldi	r26, 0x18	; 24
  90:	b1 e0       	ldi	r27, 0x01	; 1
  92:	01 c0       	rjmp	.+2      	; 0x96 <.do_clear_bss_start>

00000094 <.do_clear_bss_loop>:
  94:	1d 92       	st	X+, r1

00000096 <.do_clear_bss_start>:
  96:	ae 3b       	cpi	r26, 0xBE	; 190
  98:	b2 07       	cpc	r27, r18
  9a:	e1 f7       	brne	.-8      	; 0x94 <.do_clear_bss_loop>

So it was a little more intelligent than I thought. Not first everything 0 and next the global and static variables that need initialisation but first the global and static and next the remainder.

I did battle to find the value 5 for xyz; I initially disassembled the generated hex to see it and eventually managed with the -j .data option for avr-objdump in the above command.

@coding badly, thanks for an interesting day :slight_smile: Time well spent.