1

I have the following structure:

test.h:

extern BOOL some_variable;

inline BOOL get_some_variable()
{
    return some_variable;
}

test.c

BOOL some_variable = 10;
// some functions that change 'some_variable'.

main.c

int main()
{
    while(1) {
        if (get_some_variable()) { // do something }
    }
}

My question is, will this work as expected. By that I mean will call in main get replaced by 'some_variable'? Or will this create copies of 'some_variable' or something like that? Does the inlined function need to be declared extern somewhere?

I am aware I could just be checking 'some_variable' in main.c without the need of a function, but this way seems more elegant to me. Or is there a better way, to have a variable in other source file returned without calling a function. I want this to reduce the number of operations needed to get 'some_variable' because this is for a microcontroller.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
user1806687
  • 934
  • 1
  • 10
  • 27

2 Answers2

2

Yes, I believe the function should be declared extern somewhere, strictly, though if the function is actually inlined everywhere, you won't notice the absence of an extern definition. The standard says:

6.7.4 Function specifiers

¶7 Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.140)

140) Since an inline definition is distinct from the corresponding external definition and from any other corresponding inline definitions in other translation units, all corresponding objects with static storage duration are also distinct in each of the definitions.

As long as main.c has #include <test.h>, then you are likely to end up with the body of the function used inline — without function call overhead — in the main() program.

On the whole, it is probably safest to use static inline everywhere (as John Bollinger suggests). See also Is inline without static or extern ever useful in C, and there may well be other relevant questions on SO.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Hmmm. I read that section of the standard differently than you do, at least in part: no explicitly `extern` definition of function `get_some_variable()` is required anywhere, as long as every translation unit wanting a function of that name includes test.h, which provides an inline definition of a function of that name. – John Bollinger Nov 27 '16 at 15:58
  • @JohnBollinger: I think that the problem occurs if the function isn't inlined after all — then the `extern` definition is necessary. In this case, it is very unlikely that the function would not be inlined, but in the general case, if the function is not `static inline`, then you need an `extern` definition of the function in one TU. I'm open to discussion on the point. – Jonathan Leffler Nov 27 '16 at 16:01
  • @JonathanLeffler I've compiled my program as is and no compiler error occured. So? – user1806687 Nov 27 '16 at 16:04
  • @JonathanLeffler, My thought was that if the compiler does not have an external definition to choose, then using the inline definition is its only option. On further consideration, however, I think it is probably me who misread. If a function is declared with external linkage, then that promises that there will be an external definition somewhere. An inline definition is not an external definition, but -- and here's the tricky part -- it can still be an external *declaration*. – John Bollinger Nov 27 '16 at 16:06
  • So what are you worried about? As I noted in my comment to John, I think that the standard says that you are supposed to provide an `extern` definition of a non-static inline function, but that's primarily in case the function isn't inlined somewhere. – Jonathan Leffler Nov 27 '16 at 16:06
  • @JonathanLeffler I am not a native english speaker, so its kind of hard for me to understand what are you saying. So if I have inline BOOL get_x function defined in header file I dont need extern inline get_x somewhere else? I would however need it if in test.c there would be BOOL get_x function defined but not as inline in header? – user1806687 Nov 27 '16 at 16:10
  • 2
    In theory, you need the `extern inline` somewhere. However, if every actual call is inlined, then there is no reference to the un-inlined (`extern inline`) function to cause the linking to fail. So your code works because the function is unconditionally inlined — with your current compiler. While it's hard to see it failing with the example code, more complex functions certainly could fail. In theory, a compiler could ignore the inline altogether and always call a function, and … well, then you're supposed to provide the `extern inline` definition so that it works and the problem's yours. – Jonathan Leffler Nov 27 '16 at 16:14
2

I've come to agree with @JonathanLeffler's conclusion that the form of inline function definition you present requires an external definition somewhere of function get_some_variable(), which is not provided by your test.h. It may turn out that your compiler still builds your program successfully, however, as it may well choose everywhere to use the provided inline function instead of the falsely promised external one.

Nevertheless, what you're doing seems a bit silly. The whole point of an inline definition of a function with external linkage is to provide an optional local alternative to the external function. If you want the inline function to be used always, then it would be appropriate to declare it static in test.h:

extern BOOL some_variable;

static inline BOOL get_some_variable()
{
    return some_variable;
}

One normally wants to avoid static declarations in headers, because they get duplicated in every translation unit that includes the header, but that's exactly what you want in a case such as this.

Or on the third hand, in this particular case you could consider just accessing the variable directly, which can be done from every translation unit anyway. If you're looking to encapsulate some_variable and restrict access to it, then you need a different approach.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • What do you mean by " If you want the inline function to be used always"? Why would I want these to get duplicated in every translation unit? If files include "test.h" arent they going to get this function anyway? Isnt include just a copy-paste? – user1806687 Nov 27 '16 at 16:30
  • 1
    @user1806687, if an inline function is declared with external linkage -- which is what it has if you do not declare it `static` -- then the compiler has the option of choosing to use an external definition instead of the inline one. That would be a problem in your case, because you're not providing an external definition. If you want to deny the compiler the option of choosing an external definition -- so that in every case it chooses the inline definition you do provide -- then declare the inline function `static`, which gives it internal linkage instead of external. – John Bollinger Nov 27 '16 at 16:53
  • Yes, `#include` is analogous to a copy&paste operation. It's all about the implications of that copying and pasting. External functions and variables can be declared multiple times (i.e. via a header included into multiple translation units), without creating multiple distinct functions or variables. In contrast, every translation unit that declares an internal (`static`) function or variable gets its own function or variable of that name, visible only to it. For `static inline` functions, the advantage is that there is no promise of an external version available for the compiler to use. – John Bollinger Nov 27 '16 at 17:04