Date: Fri, 5 May 2023 12:51:24 +0200
On 05/05/2023 02:07, Alejandro Colomar via Std-Proposals wrote:
> Hi,
>
> On 5/4/23 21:24, Tom Honermann via Std-Proposals wrote:
>> On 5/4/23 1:11 PM, sasho648 via Std-Proposals wrote:
>>> So why does inline functions need to have the same sequence of tokens
>>> in different TU - imagine in a TU there is a preprocessor define that
>>> changes the function definition - it would make sense this not to be UB.
>>>
>>> In C inline functions have internal linkage - it would make the same
>>> sense for C++.
>
> What? C inline functions have the same linkage as any other function:
> external by default; internal if you use 'static'.
>
> Here's how you should use inline in C:
>
> // foo.h:
> inline int
> foo(void)
> {
> return 42;
> }
>
> // foo.c:
> extern inline int foo(void);
>
> Here's a great description of how C inline works:
> <https://www.greenend.org.uk/rjk/tech/inline.html>
>
That link is rather dated - as is your advice on how you "should" use
inline in C.
The prime use of "inline" in modern C on modern compilers is as
information to the human programmers reading the code. There are very
few use-cases where "inline" makes sense without "static", and then the
"inline" modifier is pretty much redundant except to tell readers that
this is something you view as a small helper function - the kind of
function previous generations might have written as function-like macros.
Consider the difference between a static inline function "foo", and a
non-static inline function "bar" with the same functionality.
With "foo", you always know exactly what definition is used for the
function. With "bar", there is a guessing game - the compiler might use
the local inline definition, or it might use an external definition. In
neither case do you have any guarantees that the code is actually
generated inline in the caller - it could be a stand-alone function in
the object code. But with "foo", you know the definition for that
function, while with "bar" it could be either the inline definition or
the external definition.
With "foo", you can have local modifiable static data. You can refer to
other static data and functions in the file. With "bar", you cannot.
(gcc and perhaps other compilers are far too lax on these rules - but
let's stick to standard C and defined behaviours.)
With "foo", you only need the one definition - and you can put it in a
header or a C file, according to where you want to use it. With "bar",
you /might/ need an external definition as well - or might not,
depending on how it happens to be used.
With "foo", if you actually need a non-inlined version of the function
from multiple translation units, and you don't have a smart enough
linker that can combine these, you'll waste a bit of space. If that
space is remotely close to significant, then you should not have been
making the function "inline" in the first place. In real-world usage,
the risk of extra space is irrelevant. (And I say that as someone who
works on small microcontrollers for a living.)
> Hi,
>
> On 5/4/23 21:24, Tom Honermann via Std-Proposals wrote:
>> On 5/4/23 1:11 PM, sasho648 via Std-Proposals wrote:
>>> So why does inline functions need to have the same sequence of tokens
>>> in different TU - imagine in a TU there is a preprocessor define that
>>> changes the function definition - it would make sense this not to be UB.
>>>
>>> In C inline functions have internal linkage - it would make the same
>>> sense for C++.
>
> What? C inline functions have the same linkage as any other function:
> external by default; internal if you use 'static'.
>
> Here's how you should use inline in C:
>
> // foo.h:
> inline int
> foo(void)
> {
> return 42;
> }
>
> // foo.c:
> extern inline int foo(void);
>
> Here's a great description of how C inline works:
> <https://www.greenend.org.uk/rjk/tech/inline.html>
>
That link is rather dated - as is your advice on how you "should" use
inline in C.
The prime use of "inline" in modern C on modern compilers is as
information to the human programmers reading the code. There are very
few use-cases where "inline" makes sense without "static", and then the
"inline" modifier is pretty much redundant except to tell readers that
this is something you view as a small helper function - the kind of
function previous generations might have written as function-like macros.
Consider the difference between a static inline function "foo", and a
non-static inline function "bar" with the same functionality.
With "foo", you always know exactly what definition is used for the
function. With "bar", there is a guessing game - the compiler might use
the local inline definition, or it might use an external definition. In
neither case do you have any guarantees that the code is actually
generated inline in the caller - it could be a stand-alone function in
the object code. But with "foo", you know the definition for that
function, while with "bar" it could be either the inline definition or
the external definition.
With "foo", you can have local modifiable static data. You can refer to
other static data and functions in the file. With "bar", you cannot.
(gcc and perhaps other compilers are far too lax on these rules - but
let's stick to standard C and defined behaviours.)
With "foo", you only need the one definition - and you can put it in a
header or a C file, according to where you want to use it. With "bar",
you /might/ need an external definition as well - or might not,
depending on how it happens to be used.
With "foo", if you actually need a non-inlined version of the function
from multiple translation units, and you don't have a smart enough
linker that can combine these, you'll waste a bit of space. If that
space is remotely close to significant, then you should not have been
making the function "inline" in the first place. In real-world usage,
the risk of extra space is irrelevant. (And I say that as someone who
works on small microcontrollers for a living.)
Received on 2023-05-05 10:51:35