Difference between an inline function and static inline function when accessing a static variable

StackOverflow https://stackoverflow.com/questions/21771901

  •  11-10-2022
  •  | 
  •  

Question

I encountered an interesting case while reading others code.

In the head file, defined a static variable and an inline function are simplified as following:

static int ply;

inline int WTM(){return ply;}

and the function is called in some other cpp file that include this head.

cout << ply << " " << WTM();

The strange thing is that at where this function is called, the variable ply inside that inline function has different value from the same variable just before it outside the function.

The output is 0 1;

I checked all the file and both ply and WTM() just have this single definition.

After that I have changed the code to the following:

static int ply;

static inline int WTM(){return ply;}

The two value became the same.

My compiler is g++ (GCC) 4.4.7 with default setting.

I searched about this phenomenon and get to this two link: Difference between an inline function and static inline function and http://gcc.gnu.org/onlinedocs/gcc/Inline.html but still don't understand why this could happen (especially for why they could have different values in the first situation). I wonder if someone can tell me how the compiler will expand those two pieces of code (I tried using -E but it seems not working on inline function).

Was it helpful?

Solution

It's because the static variable will be defined separately in all translation units where the header file have been included, but the (non-static) function will only be defined once. So you have multiple copies of the variable but only one copy of the functions. Which copy of the variable will the function use? I don't know, I think it's either undefined behavior or implementation defined (have to read the specification for that).

What differs when you declare the function to be static too, is that then it will be defined in each translation unit the same as the variable, and so access the variable for only that translation unit.

OTHER TIPS

Your first use of inline function without static, is undefined behaviour.

Standard 3.2.6,

There can be more than one definition of ..., ..., inline function with external linkage (7.1.2), ..., in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements:

— each definition of D shall consist of the same sequence of tokens; and

— in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity,

— ...

If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

For your first use of external inline function (without static), the name of ply, after name lookup, refer to different entity for different translation unit.

There is also one more explanation of this:

By declaring a function inline, you can direct compiler to integrate that function's code into the code for its callers.

This makes execution faster by eliminating the function-call overhead; in addition, if any of the actual argument values are constant, their known values may permit simplifications at compile time so that not all of the inline function's code needs to be included.

The effect on code size is less predictable; object code may be larger or smaller with function inline, depending on the particular case.

Inline functions is an optimization and it really “works” only in optimizing compilation. If you don't use -O, no function is really inline.

and For static inline function:

When a function is both inline and static,

if all calls to the function are integrated into the caller, and the function's address is never used, then the function's own assembler code is never referenced.

In this case, compiler does not actually output assembler code for the function, unless you specify the option -fkeep-inline-functions.

Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and neither can recursive calls within the definition).

If there is a non integrated call, then the function is compiled to assembler code as usual. The function must also be compiled as usual if the program refers to its address, because that can't be inlined.

by using reference What's the difference between “static” and “static inline” function?:

inline instructs the compiler to attempt to embed the function content into the calling code instead of executing an actual call.

For small functions that are called frequently that can make a big performance difference.

However, this is only a "hint", and the compiler may ignore it, and most compilers will try to "inline" even when the keyword is not used, as part of the optimizations, where its possible.

for example:

static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};

This tight loop will perform a function call on each iteration, and the function content is actually significantly less than the code the compiler needs to put to perform the call. inline will essentially instruct the compiler to convert the code above into an equivalent of:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

Skipping the actual function call and return

Obviously this is an example to show the point, not a real piece of code.

static refers to the scope. In C it means that the function/variable can only be used within the same translation unit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top