Outside line

I understand that the "built-in" in itself is a proposal for the compiler, and by its description it may or may not inline the function, and it will also create linked object code.

I think that the “static inline” does the same (it may or may not be inline), but it will not create reference object code when pasting (since no other module can reference it).

Where does extern inline fit into the image?

Suppose I want to replace the preprocessor macro with a built-in function and require that the function be built-in (for example, because it uses the __FILE__ and __LINE__ macros, which must be enabled for the caller, but not this called function). That is, I want to see a compiler or linker error in case the function is not inserted. Does it do extern inline? (I assume that if this is not the case, it is impossible to achieve this behavior except adhering to the macro.)

Are there any differences between C ++ and C?

Are there differences between different compiler providers and versions?

+84
c ++ c extern inline-functions
Oct 19 '08 at 15:09
source share
6 answers

in K & RC or C89, inline was not part of the language. Many compilers implemented it as an extension, but there was no specific semantics about how this works. GCC was one of the first to implement inlining, and introduced inline , static inline and extern inline constructs; most pre-C99 compilers usually follow it.

GNU89:

  • inline : the function can be inlined (this is just a hint). An exclusive version is always radiated and externally visible. Therefore, you can only have such an inline string defined in one compilation unit, and each other should see it as a function outside the line (or you will get duplicate characters during communication).
  • extern inline will not generate the version out of turn, but may call one (which you must define in some other compiler). However, the rule of one definition is applied, and the external version should have the same code as the inline in case the compiler calls it instead.
  • static inline will not generate an external visible version out of turn, although it can generate a static file. A rule with one definition does not apply, since an external character or call is never issued.

C99 (or GNU99):

  • inline : like GNU89 "extern inline"; no external visible function is emitted, but it can be called and therefore must exist.
  • extern inline : like GNU89 "inline": code is visible from the outside, so at most it can use this translation device.
  • static inline : like GNU89 "static inline". It is the only portable between gnu89 and c99

C ++:

A function that needs to be built in anywhere should be built everywhere, with the same definition. The compiler / linker will sort multiple instances of the character. There is no definition of static inline or extern inline , although many compilers have them (usually after the gnu89 model).

+121
Oct 19 '08 at 15:35
source share

I believe that you misunderstand __FILE__ and __LINE__ based on this statement:

since it uses __FILE__ and __LINE__ macros, which must be allowed for the caller, but not the function called

There are several compilation steps, and preprocessing is the first. __FILE__ and __LINE__ are replaced at this point. Therefore, by the time the compiler can consider the function for inlining, they have already been replaced.

+29
Oct 19 '08 at 15:15
source share

It looks like you are trying to write something like this:

 inline void printLocation() { cout <<"You're at " __FILE__ ", line number" __LINE__; } { ... printLocation(); ... printLocation(); ... printLocation(); 

and hope you get different values ​​printed each time. As Don says, you won’t, because __FILE__ and __LINE__ are implemented by the preprocessor, but the built-in is implemented by the compiler. Therefore, wherever you call printLocation, you will get the same result.

just so you can make it work, make printLocation a macro. (Yes I know...)

 #define PRINT_LOCATION {cout <<"You're at " __FILE__ ", line number" __LINE__} ... PRINT_LOCATION; ... PRINT_LOCATION; ... 
+12
Oct 19 '08 at 21:49
source share

The situation with inline, static inline and external inline is complicated, not least because gcc and C99 define slightly different values ​​for their behavior (and, presumably, C ++). You can find useful and detailed information about what they do in C here .

+3
Oct. 19 '08 at 21:59
source share

Macros are your choice here, not built-in functions. A rare case when macros control built-in functions. Try the following: I wrote this code "MACRO MAGIC" and it should work! Tested on gcc / g ++ Ubuntu 10.04

 //(c) 2012 enthusiasticgeek (LOGGING example for StackOverflow) #ifdef __cplusplus #include <cstdio> #include <cstring> #else #include <stdio.h> #include <string.h> #endif //=========== MACRO MAGIC BEGINS ============ //Trim full file path #define __SFILE__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/')+1 : __FILE__ ) #define STRINGIFY_N(x) #x #define TOSTRING_N(x) STRINGIFY_N(x) #define _LINE (TOSTRING_N(__LINE__)) #define LOG(x, s...) printf("(%s:%s:%s)" x "\n" , __SFILE__, __func__, _LINE, ## s); //=========== MACRO MAGIC ENDS ============ int main (int argc, char** argv) { LOG("Greetings StackOverflow! - from enthusiasticgeek\n"); return 0; } 

For several files, these macros are defined in a separate header file, including each file c / cc / cxx / cpp. Please prefer built-in functions or constant identifiers (as the case may be) over macros where possible.

+2
Aug 06 2018-12-12T00:
source share

Instead of answering “what is he doing?”, I answer “how to get him to do what I want?” There are 5 types of embedding, all available in GNU C89, C99 and C ++:

always on line if the address is not busy

Add __attribute__((always_inline)) to any ad, and then use one of the following cases to handle the possibility of receiving its address.

You probably should never use this unless you need its semantics (for example, to affect the assembly in a certain way or use alloca ). The compiler usually knows better than you if it’s worth it.

built-in and emitting a weak character (for example, C ++, it is “just make it work”)

 __attribute__((weak)) void foo(void); inline void foo(void) { ... } 

Note that this leaves a bunch of copies of the same code, and the linker selects one arbitrarily.

inline but never emits any character (leaving external links)

 __attribute__((gnu_inline)) extern inline void foo(void) { ... } 

always throw away (for one TU, to resolve the previous one)

The hint produces a weak character in C ++, but a strong character in any of the C dialects:

 void foo(void); inline void foo(void) { ... } 

Or you can do this without a hint that emits a strong character in both languages:

 void foo(void) { ... } 

Typically, you know what language your TU is in when you provide definitions, and you probably don't need to embed much.

built-in and radiating in each TU

 static inline void foo(void) { ... } 



For all of this, besides static , you can add the void foo(void) declaration above. This helps with the "best practice" of writing clean headers, and then #include separate file with inline definitions. Then, if C-style strings are used, #define defines the macro differently in one dedicated TU to provide definitions outside the string.

Do not forget extern "C" if the header can be used from either C or C ++!

0
Jul 08 '18 at 7:02
source share



All Articles