I wonder what reason might be to declare FILE *volatile fp
as volatile pointer:
int main(int argc, char **argv) {
int gc;
fe_Object *obj;
FILE *volatile fp = stdin;
fe_Context *ctx = fe_open(buf, sizeof(buf));
/* init input file */
if (argc > 1) {
fp = fopen(argv[1], "rb");
if (!fp) { fe_error(ctx, "could not open input file"); }
}
if (fp == stdin) { fe_handlers(ctx)->error = onerror; }
gc = fe_savegc(ctx);
setjmp(toplevel);
/* re(p)l */
for (;;) {
fe_restoregc(ctx, gc);
if (fp == stdin) { printf("> "); }
if (!(obj = fe_readfp(ctx, fp))) { break; }
obj = fe_eval(ctx, obj);
if (fp == stdin) { fe_writefp(ctx, obj, stdout); printf("\n"); }
}
return EXIT_SUCCESS;
}
Source: https://github.com/rxi/fe/blob/ed4cda96bd582cbb08520964ba627efb40f3dd91/src/fe.c#L854
The pointer fp
is not changing from hardware side or in interrupts by any means. It seems not changing in signal handlers either.
Projects seems to me as well written and I guess there's some reason behind that I can't understand. Please, provide some clues about that.
I would guess that volatile
is being used here for its interaction with setjmp
/longjmp
-- notice that there is a call to setjmp
in main. From the CAVEATS section of the setjmp manual page:
The compiler may optimize variables into registers, and longjmp() may restore the values of other registers in addition to the stack pointer and program counter. Consequently, the values of automatic variables are unspecified after a call to longjmp() if they meet all the following criteria:
• they are local to the function that made the corresponding setjmp() call;
• their values are changed between the calls to setjmp() and longjmp(); and
• they are not declared as volatile.
Now in this code it does not appear that fp
can be changed after the call to setjmp
, unless one of the fe_
calls is actually a macro that modifies fp
. So it would appear that the volatile
is actually unnecessary.
This is actually the most common use of volatile
for a local (rather than global) variable.