Inline functions have addresses?

R

Ravi

In section 7.1.1 of the book The C++ Programming language the author
mentions -

"inline function still has a unique variable and so do the static
variables of an inline function"

I am confused. If I have inline function then it can't have address.
Does this happen in C also?
 
H

Howard Hinnant

In section 7.1.1 of the book The C++ Programming language the author
mentions -

"inline function still has a unique variable and so do the static
variables of an inline function"

I am confused. If I have inline function then it can't have address.
Does this happen in C also?

If you take the address of an inlined function, the compiler will
outline it somewhere and give you the address of that outlined
function.

C inline functions are subtly different, and I'll let someone else
tackle that part of your question.

-Howard
 
S

SG

I am confused. If I have inline function then it can't have address.

Sure it can. Think of inline as an additional property of a function
and forget about what a compiler might or might not do w.r.t. actual
inlining. An "inline function" is just like a normal function and it
has an address as well (at least you can ask for it). But there are
two big differences in terms of semantics (I can think of):

- The one definition rule allows multiple definitions of the same
inline function (at most one definition per translation unit)
as long as the definitions are equivalent. This is not allowed
for non-inline functions.

- Any use of an inline function *requires* a definition of the
function in the translation unit where it is used. This is not
necessary for non-inline functions.

For a compiler that handles translation units independently (like most
compilers do), the benifits of these rules are:

- Inlining of an inline function is fairly easy because the
translation unit includes the function's definition.

- The compiler doesn't need to create a distinct symbol for the
inline function unless its address is taken or the function
is used but not actually inlined.

Does this happen in C also?

In C the inline keyword is just a decoration. As far as I can tell, it
doesn't have any effect on the semantics of your program (unlike in C+
+). To avoid multiple definition errors C programmers often use inline
in combination with static which makes the function to have internal
linkage.


Cheers!
SG
 
A

Andrey Tarasevich

Ravi said:
In section 7.1.1 of the book The C++ Programming language the author
mentions -

"inline function still has a unique variable and so do the static
variables of an inline function"

I am confused. If I have inline function then it can't have address.
Does this happen in C also?

You are indeed confused.

Inline functions are... well, _functions_. And as all functions, they
have addresses. Where did you get that strange idea that an inline
function "can't have address"?

The fact that the body of inline function can be _inlined_ at some (or
all) points from where this function is called has absolutely no effect
on the function itself. In other words, actual _inlining_ is something
that affects specific _calls_ to the function, but has no effect on the
functions itself. In particular, there's nothing to prevent an inline
function from having an address.
 
M

Marek Borowski

You are indeed confused.

Inline functions are... well, _functions_. And as all functions, they
have addresses. Where did you get that strange idea that an inline
function "can't have address"?
Not strange. What is reason for keeping not used code inside binary ?
(if all is inlined)

Regards

Marek
 
B

Bo Persson

Marek said:
Not strange. What is reason for keeping not used code inside binary
? (if all is inlined)

If you take its address, it must have one. :)

Otherwise the unused code can be removed.


Bo Persson
 
A

Andrey Tarasevich

Marek said:
Not strange. What is reason for keeping not used code inside binary ?
(if all is inlined)

Firstly, nobody said that it has to be kept in the final binary, if it
is really not used.

Secondly, one reason to keep it (at least at some intermediate stages of
the compilation) is that inline functions in C++ (just like any other
functions) have external linkage by default. Some implementations might
decide to generate and keep the unused body for a while, until the
compilation is pretty mush done, and it is finally known whether the
body is actually used.
 
J

Juha Nieminen

SG said:
In C the inline keyword is just a decoration. As far as I can tell, it
doesn't have any effect on the semantics of your program (unlike in C+
+). To avoid multiple definition errors C programmers often use inline
in combination with static which makes the function to have internal
linkage.

Does that mean it's not possible in C to do this (and have it work in
the same way)?

inline void foo()
{
static int counter = 0;
++counter;
...
}
 
I

Ian Collins

Does that mean it's not possible in C to do this (and have it work in
the same way)?

inline void foo()
{
static int counter = 0;
++counter;
...
}

Considering the "as if" rule, it must.
 
S

SG

  Does that mean it's not possible in C to do this (and have it work in
the same way)?

    inline void foo()
    {
        static int counter = 0;
        ++counter;
        ...
    }

As far as I know, in C, inline functions with _external_linkage_ are
subject to some restrictions. One of these restrictions is that they
are not allowed to have static variables. So, your example is not
valid C99.
 
J

James Kanze

Does that mean it's not possible in C to do this (and have it work in
the same way)?
inline void foo()
{
static int counter = 0;
++counter;
...
}

IIRC (and this is just from memory---I don't have my copy of the
C standard around to check), the above is undefined behavior in
C (but not in C++, where the compiler is required to make it
work).
 
J

Juha Nieminen

James Kanze said:
IIRC (and this is just from memory---I don't have my copy of the
C standard around to check), the above is undefined behavior in
C (but not in C++, where the compiler is required to make it
work).

Is there a good reason for this?
 
S

SG

  Is there a good reason for this?

From http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
(draft of C99+TC1+TC2+TC3 from 2007)

6.7.4/3:
"An inline definition of a function with external linkage shall not
contain a definition of a modifiable object with static storage
duration, and shall not contain a reference to an identifier with
internal linkage."

6.7.4/6:
"[...] 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."

If I understand this correctly, inline in C is more restrictive than
in C++ (w.r.t. static variables for example) and you have to (or
should) provide an "external definition" of an inline function with
external linkage in exactly one translation unit like this:

----------8<----------

// foo.h
#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED

inline int add(int a, int b) {return a+b;}

#endif

----------8<----------

// foo.c
#include "foo.h"

// This declaration makes the definition from the
// header an "external definition" in *this* TU.
extern inline int add(int,int);

----------8<----------

Did I get this right?

Cheers!
SG
 
S

SG

----------8<----------

  // foo.h
  #ifndef FOO_H_INCLUDED
  #define FOO_H_INCLUDED

  inline int add(int a, int b) {return a+b;}

  #endif

----------8<----------

  // foo.c
  #include "foo.h"

  // This declaration makes the definition from the
  // header an "external definition" in *this* TU.
  extern inline int add(int,int);

----------8<----------

Did I get this right?

It seems so. But using the header in another file and compiling
+linking it with GCC like this:
> gcc -o test test.c foo.c

leads to the following error:

test.c: multiple definition of 'add'
foo.c: first definition here

Now, if I add the option "-std=c99" this goes away and it compiles
+links just fine. It seems that GCC in its default mode doesn't
respect the C99 rules regarding inline. It doesn't seem to distinguish
between "inline definition" and "extern definition" and always
generates a symbol for the function (which explains the linker error)
*unless* you specifically enable the C99 mode.

Ok, so, in C99 you don't *have* to use inline in combination with
static and inline is not just a "decoration" but comes with its own
set of rules. I stand corrected.

Cheers!
SG
 
J

James Kanze

Is there a good reason for this?

Make things easier for the compiler writer.

Making a local static work in an inline function with external
linkage requires some special handling. The same special
handling is needed for templates in C++, so making them work in
C++ is basically free. In C, the compiler would have to add
this special handling, just for static local variables in inline
functions.
 
J

Juha Nieminen

James Kanze said:
Make things easier for the compiler writer.

I have always had the opinion that programs (in this particular case
compilers) should make the user's life simpler, not the other way around
(iow. restricting the user from using a logical feature which the language
could obviously support because such a restriction makes writing a compiler
easier is going in the wrong direction in the who-is-helping-who line).

(This is the same reason why I strongly oppose eg. MathML, compared to
something like LaTeX equations. MathML exists to make it easier for
programmers to write programs which parse mathematical expressions, at
the cost of greatly complexifying the work of the user, who needs to
write the mathematical expression in MathML. LaTeX goes the other way
around: It makes it as easy as possible for the user to write mathematical
expressions, at the cost of greatly complexifying the program that parses
the expression. This is the correct direction. Programs are there to help
users, not the other way around.)
 
J

James Kanze

I have always had the opinion that programs (in this particular case
compilers) should make the user's life simpler, not the other way around
(iow. restricting the user from using a logical feature which the language
could obviously support because such a restriction makes writing a compiler
easier is going in the wrong direction in the who-is-helping-who line).

I tend to agree. In the case of C: historically, C was first
designed for very small systems, and implemented by very small
teams (two or three people). If you didn't make the compiler
simpler for for the compiler writer, you didn't get a compiler.
Today, this still influences the "taste" of C.

With regards to inline functions, I sort of agree with the
C committee. The mechanism is rather heavy, and requiring it
uniquely for inline functions does seem a bit overdoing things.
(But then, given the size and performance of modern hardware,
I don't see the point of C anyway. Anything C can do, C++ can
do better.)
 
J

Juha Nieminen

James Kanze said:
With regards to inline functions, I sort of agree with the
C committee. The mechanism is rather heavy, and requiring it
uniquely for inline functions does seem a bit overdoing things.

Strictly speaking, isn't it something that complicates the *linker*
rather than the compiler itself (other than the compiler having to
generate instructions for the linker to merge the static variables
into one)?
 
S

SG

  Strictly speaking, isn't it something that complicates the *linker*
rather than the compiler itself (other than the compiler having to
generate instructions for the linker to merge the static variables
into one)?

Yes, I think that's exactly the case. The rules of C99 inline seem to
easily support "simple linkers" whereas a straight forward C++
implementation would use a linker that simply "merges" certain
multiple definitions (inline functions, function templates, static
members of class templates) and complains about others (non-inline non-
template functions, other static objects). Apparently, the GCC C++
compiler marks some symbols as "weak" to tell the linker to ignore
multiple definitions. Of course, your object file format has to
support this as well. I've already seen an embedded "C linker" choke
on compiled C++ code. It wasn't able to cope with an inline function.

Cheers!
SG
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top