Is there any macro to achieve or undo this?

void setup(){
  Serial.begin(115200);
}//setup()

void loop(){
  foo();
  delay(500);
}//loop()

void foo(){
  static int bar = foobar();
  Serial.print("bar:")
  Serial.println(bar);
  bar++;
}//foo()

int foobar(){
  Serial.println("This is foobar");
  return 0;
}//foobar()

In this program foobar() is called exactly once at the first run of foo(). To me that means that the compiler must insert some code to skip the line:  static int bar = foobar(); on consecutive calls. It must also have some means to keep track of weather it is the fist call or not in runtime.

My question: Does anyone know of these mechanisms and how to manipulate them? That is

  • Check if this is the first call without declaring a static variable
  • Reset the flag that indicates a already called function

It's your use of static. Since you only call foobar as part of the initialisation of a static variable, it only gets called in the first call of foo().

Remove the word static and it'll be called every time.

Alternatively you could still use a static variable thus.

static int bar;
bar = foobar();

Because the variable is declared static, it needs to be initialized once. That happens by calling foobar(). Once the variable has a value, foobar() isn't called again.

Actually, if you put Serial.print() statements in setup(), loop(), foo(), and foobar(), you'll see that foobar() is probably not called when you think it is.

You can use boolean variables, and check them to see if it is necessary to call any function.

This was not what i was asking. I know about static variables and when they are called. My question was how the mechanisms causing this work, if they are accessible and if they could be manipulated. What i want to do is

  • Call foobar once at the first call without the need for a static variable or some other code but just by utilizing what the compiler does with a static variable
  • Be able to reset the flag so that foobar() is called again at some later time

Call foobar once at the first call without the need for a static variable or some other code but just by utilizing what the compiler does with a static variable

Those requirements look incompatible. You need to do something, so why not just have foobar() set a boolean variable indicating that that is has been called and check that before calling it again. To call it again just change the boolean variable.

I want to know how it works inside. As i said the mechanism achieving this must be there. So how does it work and how can i utilize it.
But you are probably right, this mechanism would most likely not be inserted unless there is need for it e.g there is a static variable declared

I took an objdump but it doesnt tell me much. Except that it has something to do with __cxa_guard_acquire and __cxa_guard_release

000000d0 <_Z3foov>:
  d0:	80 91 24 01 	lds	r24, 0x0124
  d4:	88 23       	and	r24, r24
  d6:	81 f4       	brne	.+32     	; 0xf8 <_Z3foov+0x28>
  d8:	84 e2       	ldi	r24, 0x24	; 36
  da:	91 e0       	ldi	r25, 0x01	; 1
  dc:	0e 94 a4 03 	call	0x748	; 0x748 <__cxa_guard_acquire>
  e0:	89 2b       	or	r24, r25
  e2:	51 f0       	breq	.+20     	; 0xf8 <_Z3foov+0x28>
  e4:	0e 94 5f 00 	call	0xbe	; 0xbe <_Z6foobarv>
  e8:	90 93 2d 01 	sts	0x012D, r25
  ec:	80 93 2c 01 	sts	0x012C, r24
  f0:	84 e2       	ldi	r24, 0x24	; 36
  f2:	91 e0       	ldi	r25, 0x01	; 1
  f4:	0e 94 ae 03 	call	0x75c	; 0x75c <__cxa_guard_release>
  f8:	8f eb       	ldi	r24, 0xBF	; 191
  fa:	91 e0       	ldi	r25, 0x01	; 1
  fc:	6f e0       	ldi	r22, 0x0F	; 15
  fe:	71 e0       	ldi	r23, 0x01	; 1
 100:	0e 94 db 04 	call	0x9b6	; 0x9b6 <_ZN5Print5printEPKc>
 104:	60 91 2c 01 	lds	r22, 0x012C
 108:	70 91 2d 01 	lds	r23, 0x012D
 10c:	8f eb       	ldi	r24, 0xBF	; 191
 10e:	91 e0       	ldi	r25, 0x01	; 1
 110:	4a e0       	ldi	r20, 0x0A	; 10
 112:	50 e0       	ldi	r21, 0x00	; 0
 114:	0e 94 bc 04 	call	0x978	; 0x978 <_ZN5Print7printlnEii>
 118:	80 91 2c 01 	lds	r24, 0x012C
 11c:	90 91 2d 01 	lds	r25, 0x012D
 120:	01 96       	adiw	r24, 0x01	; 1
 122:	90 93 2d 01 	sts	0x012D, r25
 126:	80 93 2c 01 	sts	0x012C, r24
 12a:	08 95       	ret

00000748 <__cxa_guard_acquire>:
 748:	fc 01       	movw	r30, r24
 74a:	20 e0       	ldi	r18, 0x00	; 0
 74c:	30 e0       	ldi	r19, 0x00	; 0
 74e:	80 81       	ld	r24, Z
 750:	88 23       	and	r24, r24
 752:	11 f4       	brne	.+4      	; 0x758 <__cxa_guard_acquire+0x10>
 754:	21 e0       	ldi	r18, 0x01	; 1
 756:	30 e0       	ldi	r19, 0x00	; 0
 758:	c9 01       	movw	r24, r18
 75a:	08 95       	ret

0000075c <__cxa_guard_release>:
 75c:	fc 01       	movw	r30, r24
 75e:	81 e0       	ldi	r24, 0x01	; 1
 760:	80 83       	st	Z, r24
 762:	08 95       	ret

Knowing how it works as an academic exercise is one thing, but wasting time on trying to interfere with it is another. It seems to me that you would need to write some assembly language commands to do it and if you are going to do that why not just use C++ and let the compiler do the heavy lifting ?

I dont think trying to interfere is a waste of time. Much knowledge has been gained that way. I got this working:

void setup(){
  Serial.begin(115200);
}//setup()

void loop(){
  foo();
  delay(500);
}//loop()

void foo(){
  static int bar = foobar();
  Serial.print("bar:");
  Serial.println(bar);
  bar++;
  if(bar == 10) _ZGVZ3foovE3bar = 0;
}//foo()

int foobar(){
  Serial.println("This is foobar");
  return 0;
}//foobar()

nilton61:
I want to know how it works inside. As i said the mechanism achieving this must be there. So how does it work and how can i utilize it.
But you are probably right, this mechanism would most likely not be inserted unless there is need for it e.g there is a static variable declared

Ofcourse there is a mechanism inside, but it's an inherent part of C++, not something you can access.
What the people above are saying is the best way of handling it. You seem to have 2 requirements: making sure it is initialized, and be able to cause it to get reinitialized on demand.
For both just a flag indicating if it has been initialized is required. On startup it's false, so before using the value, initialize it and set the flag to true. If you want to force a reinitialization, just set the flag to false again, and the next call for it will initialize it again.

It's not because one of the side effects of a static variable is immediate initialization, that trying to abuse it for this goal is in any sense a good idea (or even a possible idea). How it does that is not via a macro or anything else you can access, but something deep internal you won't be able to reach, and if you knew how to reach it, you'd know why you would never try to mess with it.

If you've really got your mind set on using this static mechanism for this, i hope you're ready for countless hours of learning the C++ compiler internals :). enjoy

Which of course might break with the next upgrade of gcc.

nilton61:
I dont think trying to interfere is a waste of time. Much knowledge has been gained that way. I got this working:

void setup(){

Serial.begin(115200);
}//setup()

void loop(){
 foo();
 delay(500);
}//loop()

void foo(){
 static int bar = foobar();
 Serial.print("bar:");
 Serial.println(bar);
 bar++;
 if(bar == 10) _ZGVZ3foovE3bar = 0;
}//foo()

int foobar(){
 Serial.println("This is foobar");
 return 0;
}//foobar()

And now you have a piece of incredibly fragile and obtuse code that depends on undocumented behavior in the compiler that will, in all probability, stop working at some point in the future when some minor change is made in the compiler. And it will be absolutely incomprehensible to anyone else looking at your code. A year from now, even you won't remember why you did it. And for what benefit? What do you gain over one or two lines of simple, obvious, robust c code?

What you're trying to do is FAR better done in c code.

Regards,
Ray L.

Of course it does. And i got it working, which does not mean that i am going to use it. But in my world ALL knowledge is beneficial. And i have encountered countless situations where knowledge gained by curiosity or just for the challenge of it turned out to be extremely useful in some situation that is completely unforeseeable.

Because the variable is declared static, it needs to be initialized once.

A "static" variable, is a variable with a single, persistent, instance. That doesn't necessarily mean it is a constant.

nilton61:
Of course it does. And i got it working, which does not mean that i am going to use it. But in my world ALL knowledge is beneficial. And i have encountered countless situations where knowledge gained by curiosity or just for the challenge of it turned out to be extremely useful in some situation that is completely unforeseeable.

Glad to see you know better than to use it ^^
And your low level debugging skills are pretty good :). But unless you've got a love for reverse engineering programs, and need to know what it means when you encounter such things, i agree with the others that this exercise was pretty pointless...
Doing all that work and then finding such a solution for such a trivial issue to solve?

I just happen to have a love for challenges. And that served me well over the years. And it wasn't that hard. And the real knowledge gain wasn't in solving the original problem but to learn how to make and use objectdumps for both the code and the symbol table. And on a more general level how search for and filter that kind of information

nilton61:
I dont think trying to interfere is a waste of time. Much knowledge has been gained that way. I got this working:

void setup(){

Serial.begin(115200);
}//setup()

void loop(){
  foo();
  delay(500);
}//loop()

void foo(){
  static int bar = foobar();
  Serial.print("bar:");
  Serial.println(bar);
  bar++;
  if(bar == 10) _ZGVZ3foovE3bar = 0;
}//foo()

int foobar(){
  Serial.println("This is foobar");
  return 0;
}//foobar()

Fair play to you but I don't think this is very portable. You've got to untangle the name mangling which may not be consistent. But I agree, it's not entirely a wasted exercise.

Did you try adding Serial.print() statements to the functions involved? You would have seen that foobar() was called BEFORE setup(), when the sketch first starts, and the variable needs its initial value.

Not, it doesn't.

void setup(){
  Serial.begin(115200);
  Serial.println("setup");
}//setup()

void loop(){
  foo();
  delay(500);
}//loop()

void foo(){
  static int bar = foobar();
  Serial.print("bar:");
  Serial.println(bar);
  bar++;
  if(bar == 10) _ZGVZ3foovE3bar = 0;
}//foo()

int foobar(){
  Serial.println("This is foobar");
  return 0;
}//foobar()

resluts in the following:

setup
This is foobar
bar: 0
bar: 1
bar: 2
bar: 3
bar: 4
bar: 5
bar: 6
bar: 7
bar: 8
bar: 9
This is foobar
bar: 0
bar: 1

Static local variables are initialized only when they are first used. In this case, the static local variable bar is initialized the first time foo() is called, so foobar() is called at that time and no earlier.