3

In my question I originally asked these four questions

  1. In C99 compilers, is the behavior of inline implementation defined when it comes to inlining across translation units?
  2. If so, should it be avoided?
  3. Is there some other generally accepted way of doing this?
  4. If my inline function doesn't get inlined everywhere, would I at least get some sort of linker error?

After my OP I discovered that the first question has been discussed at length already in the following threads:

There are more threads on this topic, but these two seemed to hit the nail on the head.

So, based on these two discussions we can see that the answer to question 1 is YES. Compilers definitely have some freedom W.R.T. how they handle the inline specifier.

We also see that for this to work inline functions must be defined in a header.

Then beyond that the following options exist:

  1. The function definition in the header may have a static specifier.
  2. If the header definition does not have a static specifier, it may be declared via extern in some common header file that all C files calling the function will also #include.
  3. If methods 2 and 3 are not used, method 4 would be to declare this inline function via extern in every C file that wishes to call it.

So, now that all of that explanation is out of the way, I would like to refocus this question on my original items #2 and #3 – should I even be doing this, and if so what's the most acceptable way?

Should I be doing this - or should this be avoided as much as possible?

Consider my application – I have a one line function in a driver that is called frequently (≈ several hundred times a second), but only from 3 or 4 other places. So using inline will not contribute to code bloat – in fact the result will be negligible. Gregory Pakosz outlines when to use an inline function and when not to nicely in this answer. So therefore, the answer would be very clear if this were one function being used in one translation unit. But that's not what I am asking.

In this situation I do not need to inline this function. But should I? I will probably never notice any performance difference because I inlined just this one function. But I am trying to figure out if I should make this my general practice in all similar situations. If I inline short functions that are frequently called more aggressively I may see a performance improvement. (My runtime environment is a low power 16bit RISC MCU – that's probably an important detail.)

The reason for asking is this is because there seems to be a disagreement among programmers about this. Is it bad etiquette for some reason to inline functions across translation units (no matter how you do it), and if so, why?

Assuming I do inline functions across translation units, what's the least detestable or most acceptable way?

Putting static in a header seems to work well and may be the most portable way to do it. This was pointed out by pts in the comments and by and buzz in the answers. On the surface it seems like I am using static to facilitate using something globally – which is nuts! But I suppose I can more correctly think about it like this: every function that inlines this function will have its own static copy as if it were defined in each of the respective C files as static inline. If that understanding is correct then it seems like the behavior would always be predictable – the linker would have to give me notice if there are two functions with the same name in a translation unit.

I am not sure how I feel about declaring a functions via extern in a header. The wording in 6.7.4 is that external definition in another translation unit is “not forbidden”.

4

1 回答 1

2

我认为您的 driver.h 应该是这样的:

static inline void foo(void)
{
    <one line>;
}

而且你的 bar.c 不需要extern inline void foo(void);,只需调用foo();,它就可以工作。

至于If my inline function doesn't get inlined everywhere like it should - would I at least get some sort of linker error warning me that a certain reference couldn't be found

您必须在编译时显式使用优化选项,然后您将内联函数实际内联。gcc bar.c -O2. 你可以用它objdump来检查你的代码的汇编代码,你会发现内联函数被内联,而不是调用foo,但在那里被内联。

于 2014-08-21T06:02:30.283 回答