Inline functions and linkage

Discussion in 'C Programming' started by kid joe, May 26, 2009.

  1. kid joe

    kid joe Guest

    Hi all,

    Im very confused about how you should provide inline functions in a
    library. Lets say the library is libjoe with headerfile <joe.h>. There
    seem to be a few possibilities:

    1) have the function defined in joe.h as static inline.

    2) have the function defined in joe.h as inline and also include
    an extern inline prototype for it in joe.h. (Make sure to use #pragma once
    in joe.h)

    3) have the function defined as inline in one of the *.c files
    that make up libjoe, and put an extern inline prototype in joe.h.

    Which of these is the best?

    Also I guess it shouldnt be possible to call a private function from
    libjoe (ie a static function in one of the *.c files that make up libjoe)
    inside an inline function exported by libjoe, even though it would be
    possible to call a static function in a non-inline function exported by
    libjoe. How is that enforced? Is it by the compiler or the linker?

    Cheers,
    Joe


    --
    ...................... o _______________ _,
    ` Good Evening! , /\_ _| | .-'_|
    `................, _\__`[_______________| _| (_|
    ] [ \, ][ ][ (_|
     
    kid joe, May 26, 2009
    #1
    1. Advertising

  2. kid joe

    jameskuyper Guest

    kid joe wrote:
    > Hi all,
    >
    > Im very confused about how you should provide inline functions in a
    > library. Lets say the library is libjoe with headerfile <joe.h>. There
    > seem to be a few possibilities:
    >
    > 1) have the function defined in joe.h as static inline.
    >
    > 2) have the function defined in joe.h as inline and also include
    > an extern inline prototype for it in joe.h. (Make sure to use #pragma once
    > in joe.h)
    >
    > 3) have the function defined as inline in one of the *.c files
    > that make up libjoe, and put an extern inline prototype in joe.h.
    >
    > Which of these is the best?


    Option 1 works, and it allows you to avoid the restrictions on inline
    functions with external linkage: it can define a modifiable object
    with static storage duration, and it can refer to identifiers with
    internal linkage (6.7.4p2).

    Option 2 is bad, since it provides only inline definitions of the
    function. "It is unspecified whether a call to the
    function uses the inline definition or the external
    definition." (6.7.4p6) Therefore, you risk getting a link failure if
    the compiler decides to call the non-existent external definition of
    the function. Also, like most #pragma's, #pragma once is non-portable.

    Option 3 is bad, because joe.h is unusable everywhere except the *.c
    file that contains the actual definition of the 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." (6.7.4p6). This "shall"
    does not occur in a "Constraints" section, so the behavior is
    undefined if you violate it.

    Option 4 would be to provide an inline file scope definition of the
    function in joe.h, so it has implicitly external linkage, yet also
    qualfies as an inline definition. Then, in the joe.c file, declare the
    function with extern before #including joe.h, thereby making it an
    external defintion. This gives the compiler the choice of either using
    the inline definition from joe.h, or the external definition from
    joe.c, whichever it thinks will produce the best results. As a general
    rule the more freedom you give your compiler, the better the code that
    it can generate. You should only restrict it's options if you don't
    trust it to make the right choice.

    > Also I guess it shouldnt be possible to call a private function from
    > libjoe (ie a static function in one of the *.c files that make up libjoe)
    > inside an inline function exported by libjoe, even though it would be
    > possible to call a static function in a non-inline function exported by
    > libjoe. How is that enforced? Is it by the compiler or the linker?


    It's a constraint violation: "An inline definition of a function with
    external linkage ... shall not contain a reference to an identifier
    with internal linkage." (6.7.4p2) This "shall" occurs in a
    "Constraints" section, so a diagnostic is required. This constraint
    can be diagnosed at compile time; there's no need to wait for link
    time before issuing the diagnostic.
     
    jameskuyper, May 27, 2009
    #2
    1. Advertising

  3. kid joe

    user923005 Guest

    On May 26, 2:37 pm, kid joe <> wrote:
    > Hi all,
    >
    > Im very confused about how you should provide inline functions in a
    > library. Lets say the library is libjoe with headerfile <joe.h>. There
    > seem to be a few possibilities:
    >
    > 1) have the function defined in joe.h as static inline.
    >
    > 2) have the function defined in joe.h as inline and also include
    > an extern inline prototype for it in joe.h. (Make sure to use #pragma once
    > in joe.h)
    >
    > 3) have the function defined as inline in one of the *.c files
    > that make up libjoe, and put an extern inline prototype in joe.h.
    >
    > Which of these is the best?
    >
    > Also I guess it shouldnt be possible to call a private function from
    > libjoe (ie a static function in one of the *.c files that make up libjoe)
    > inside an inline function exported by libjoe, even though it would be
    > possible to call a static function in a non-inline function exported by
    > libjoe. How is that enforced? Is it by the compiler or the linker?


    The best way is usually to let the compiler choose.
    Most compilers have some kind of option for: 'Let Mr. Compiler inline
    whatever functions he wants to, wherever Mr. Compiler likes and not
    inline them if Mr. Compiler does not think it is a good idea.'

    Sometimes, we know better than the compiler. In that case I would use
    option 1, probably.
     
    user923005, May 27, 2009
    #3
  4. kid joe

    kid joe Guest

    On Tue, 26 May 2009 16:09:52 -0700, jameskuyper wrote:
    > kid joe wrote:
    >> Hi all,
    >>
    >> Im very confused about how you should provide inline functions in a
    >> library. Lets say the library is libjoe with headerfile <joe.h>. There
    >> seem to be a few possibilities:
    >>
    >> 1) have the function defined in joe.h as static inline.
    >>
    >> 2) have the function defined in joe.h as inline and also include
    >> an extern inline prototype for it in joe.h. (Make sure to use #pragma once
    >> in joe.h)
    >>
    >> 3) have the function defined as inline in one of the *.c files
    >> that make up libjoe, and put an extern inline prototype in joe.h.
    >>
    >> Which of these is the best?

    >
    > Option 1 works, and it allows you to avoid the restrictions on inline
    > functions with external linkage: it can define a modifiable object
    > with static storage duration, and it can refer to identifiers with
    > internal linkage (6.7.4p2).
    >
    > Option 2 is bad, since it provides only inline definitions of the
    > function. "It is unspecified whether a call to the
    > function uses the inline definition or the external
    > definition." (6.7.4p6) Therefore, you risk getting a link failure if
    > the compiler decides to call the non-existent external definition of
    > the function. Also, like most #pragma's, #pragma once is non-portable.
    >
    > Option 3 is bad, because joe.h is unusable everywhere except the *.c
    > file that contains the actual definition of the 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." (6.7.4p6). This "shall"
    > does not occur in a "Constraints" section, so the behavior is
    > undefined if you violate it.
    >
    > Option 4 would be to provide an inline file scope definition of the
    > function in joe.h, so it has implicitly external linkage, yet also
    > qualfies as an inline definition. Then, in the joe.c file, declare the
    > function with extern before #including joe.h, thereby making it an
    > external defintion. This gives the compiler the choice of either using
    > the inline definition from joe.h, or the external definition from
    > joe.c, whichever it thinks will produce the best results. As a general
    > rule the more freedom you give your compiler, the better the code that
    > it can generate. You should only restrict it's options if you don't
    > trust it to make the right choice.
    >
    >> Also I guess it shouldnt be possible to call a private function from
    >> libjoe (ie a static function in one of the *.c files that make up libjoe)
    >> inside an inline function exported by libjoe, even though it would be
    >> possible to call a static function in a non-inline function exported by
    >> libjoe. How is that enforced? Is it by the compiler or the linker?

    >
    > It's a constraint violation: "An inline definition of a function with
    > external linkage ... shall not contain a reference to an identifier
    > with internal linkage." (6.7.4p2) This "shall" occurs in a
    > "Constraints" section, so a diagnostic is required. This constraint
    > can be diagnosed at compile time; there's no need to wait for link
    > time before issuing the diagnostic.


    Hi James,

    Thanks for the explanations. I find this a confusing area of C99, not
    covered in books like K&R and also different semantics from "that other
    language"...

    Cheers,
    Joe


    --
    ...................... o _______________ _,
    ` Good Evening! , /\_ _| | .-'_|
    `................, _\__`[_______________| _| (_|
    ] [ \, ][ ][ (_|
     
    kid joe, May 27, 2009
    #4
  5. kid joe

    Guest

    On May 26, 6:09 pm, jameskuyper <> wrote:
    > kid joe wrote:
    > > Hi all,

    >
    > > Im very confused about how you should provide inline functions in a
    > > library. Lets say the library is libjoe with headerfile <joe.h>. There
    > > seem to be a few possibilities:

    >
    > > 1) have the function defined in joe.h as static inline.

    >
    > > 2) have the function defined in joe.h as inline and also include
    > > an extern inline prototype for it in joe.h. (Make sure to use #pragma once
    > > in joe.h)

    >
    > > 3) have the function defined as inline in one of the *.c files
    > > that make up libjoe, and put an extern inline prototype in joe.h.

    >
    > > Which of these is the best?

    >
    > Option 1 works, and it allows you to avoid the restrictions on inline
    > functions with external linkage: it can define a modifiable object
    > with static storage duration,


    Yes, but since he intends to put the function definition in a header
    file, he probably won't get the desired effect (there will be a
    different copy of the variable for each file that includes the header
    file).

    > and it can refer to identifiers with
    > internal linkage (6.7.4p2).


    It's unlikely that he needs to to that, also due to the fact that the
    function will be placed in a header file (why would you define a
    variable with static storage duration in a header file?).

    > Option 2 is bad, since it provides only inline definitions of the
    > function. "It is unspecified whether a call to the
    > function uses the inline definition or the external
    > definition." (6.7.4p6) Therefore, you risk getting a link failure if
    > the compiler decides to call the non-existent external definition of
    > the function.


    Never heard of such an issue. Doesn't an inline definition also
    provide an external definition? As you say below:

    > Option 4 would be to provide an inline file scope definition of the
    > function in joe.h, so it has implicitly external linkage, [...]

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Option 2 looks fine to me, but remove both the "extern inline"
    prototype and the #pragma directive.

    Sebastian
     
    , May 27, 2009
    #5
  6. kid joe

    jameskuyper Guest

    wrote:
    > On May 26, 6:09 pm, jameskuyper <> wrote:
    > > kid joe wrote:
    > > > Hi all,

    > >
    > > > Im very confused about how you should provide inline functions in a
    > > > library. Lets say the library is libjoe with headerfile <joe.h>. There
    > > > seem to be a few possibilities:

    > >
    > > > 1) have the function defined in joe.h as static inline.

    > >
    > > > 2) have the function defined in joe.h as inline and also include
    > > > an extern inline prototype for it in joe.h. (Make sure to use #pragma once
    > > > in joe.h)

    > >
    > > > 3) have the function defined as inline in one of the *.c files
    > > > that make up libjoe, and put an extern inline prototype in joe.h.

    > >
    > > > Which of these is the best?

    > >
    > > Option 1 works, and it allows you to avoid the restrictions on inline
    > > functions with external linkage: it can define a modifiable object
    > > with static storage duration,

    >
    > Yes, but since he intends to put the function definition in a header
    > file, he probably won't get the desired effect (there will be a
    > different copy of the variable for each file that includes the header
    > file).


    Possibly he does want to have a different copy of the variable for
    each file. He asked us "which of these is best", without giving any
    details about what the function does. Option 1 does permit some things
    not permitted by the other options; more importantly, the standard
    goes out of its way to give permission for these things to be done -
    the committee must have felt that there was some potential use for
    those things, and I agree.

    Please note that the modifiable object with static storage duration
    need not be defined, or even declared, in the same header as the
    inline function; it needn't even have the same type in all the places
    where that header is #included, so long as the way it is used in the
    inline function is compatible with all of the different types it
    actually gets defined with.

    > > and it can refer to identifiers with
    > > internal linkage (6.7.4p2).

    >
    > It's unlikely that he needs to to that, also due to the fact that the
    > function will be placed in a header file (why would you define a
    > variable with static storage duration in a header file?).


    Please note that the standard refers to identifiers, not just
    variables. The identifier could be another function with internal
    linkage. Furthermore, neither the definition, nor even a declaration,
    for this identifier needs to be in the header file.

    One obvious reason for defining an object or function with static
    storage duration in a header file would be to ensure that it has the
    same definition everywhere it is used. So why not make it a single
    external definition? In the case of variables, possibly because you
    want that variable to have a different value in each translation unit
    - one obvious use of this would be to define a counter which keeps
    track of how often the inline function is used in each module. In the
    case of functions, the same could apply to any variables with static
    storage duration defined in the function, but another reason for doing
    so would be that the function referred to is also inline.

    > > Option 2 is bad, since it provides only inline definitions of the
    > > function. "It is unspecified whether a call to the
    > > function uses the inline definition or the external
    > > definition." (6.7.4p6) Therefore, you risk getting a link failure if
    > > the compiler decides to call the non-existent external definition of
    > > the function.

    >
    > Never heard of such an issue. Doesn't an inline definition also
    > provide an external definition? As you say below:


    "An inline definition does not provide an external definition for the
    function," (6.7.4p6).

    > > Option 4 would be to provide an inline file scope definition of the
    > > function in joe.h, so it has implicitly external linkage, [...]

    > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    Implicit external linkage gives the compiler permission to make use of
    an external definition defined in some other translation unit, but
    does not give the compiler permission to create one in the current
    translation unit. An inline function explicitly declared with "extern"
    is not an inline definition (6.7.4p6), and therefore does created an
    external definition.
     
    jameskuyper, May 27, 2009
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Grumble

    inline keyword and linkage

    Grumble, Feb 14, 2005, in forum: C++
    Replies:
    20
    Views:
    858
    E. Robert Tisdale
    Feb 15, 2005
  2. Daniel Vallstrom
    Replies:
    2
    Views:
    2,054
    Kevin Bracey
    Nov 21, 2003
  3. Nagrik
    Replies:
    5
    Views:
    502
    James Kanze
    Nov 28, 2007
  4. Rahul
    Replies:
    3
    Views:
    480
    James Kanze
    Feb 28, 2008
  5. Replies:
    1
    Views:
    613
    Michael DOUBEZ
    Sep 12, 2008
Loading...

Share This Page