linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Function pointers to inline functions
@ 2007-04-04 17:09 Shriramana Sharma
  2007-04-04 18:23 ` Glynn Clements
  2007-04-04 18:33 ` Steve Graegert
  0 siblings, 2 replies; 12+ messages in thread
From: Shriramana Sharma @ 2007-04-04 17:09 UTC (permalink / raw)
  To: linux-c-programming

[-- Attachment #1: Type: text/plain, Size: 539 bytes --]

Hello.

As per my understanding, an inline function is replaced in place by the 
compiler with the body of the function, so it does not have a separate 
location in memory in contrast with a regular function. This being so, 
how is it possible to extract a pointer to an inline function and 
effectively use it?

See the attached two examples. They work and though it's a good thing 
for my project that I can extract a pointer to an inline function I do 
not understand how it is possible.

Please explain. Thank you.

Shriramana Sharma.

[-- Attachment #2: function-pointers-1.cpp --]
[-- Type: text/x-c++src, Size: 1315 bytes --]

#include "stdio.h"

inline void square ( int a ) { printf ( "The square of %d is %d\n", a, a * a ) ; }
inline void cube ( int a ) { printf ( "The cube of %d is %d\n", a, a * a * a ) ; }
inline void fourthpower ( int a ) { printf ( "The fourth power of %d is %d\n", a, a * a * a * a ) ; }

void ( * functionpointers [ 3 ] ) ( int ) ;
/*
the above line declares an array called functionpointers that has three ( 3 ) elements which are all pointers ( * ) to functions which take a single integer as parameter ( int ) and return nothing ( void ) and do not modify the contents of the class in anyway ( const )
*/

void executefunction ( int functionnumber, int inputforfunction )
{
	if ( functionnumber < 0 || functionnumber > 2 ) return ;
	( * functionpointers [ functionnumber ] ) ( inputforfunction ) ;
	// this line calls the function which is pointed ( * ) to by the functionnumber-th element of the functionpointers array which is a member of the object pointed to by the current object pointer ( this ) and passes the function the value of the variable inputforfunction as a parameter
}

int main ( void )
{
	functionpointers [ 0 ] = & square ;
	functionpointers [ 1 ] = & cube ;
	functionpointers [ 2 ] = & fourthpower ;
	
	int count ;
	for ( count = 0; count < 3; count ++ )
		executefunction ( count, 2 ) ;
}

[-- Attachment #3: function-pointers-2.cpp --]
[-- Type: text/x-c++src, Size: 1448 bytes --]

#include "stdio.h"

inline int square ( int a ) { return a * a ; }
inline int cube ( int a ) { return a * a * a ; }
inline int fourthpower ( int a ) { return a * a * a * a ; }
inline int squarepluscube ( int a ) { return square ( a ) + cube ( a ) ; }
inline int squarepluscubeplusfourthpower ( int a ) { return squarepluscube ( a ) + fourthpower ( a ) ; }

int ( * functionpointers [ 5 ] ) ( int ) ;
/*
the above line declares an array called functionpointers that has three ( 3 ) elements which are all pointers ( * ) to functions which take a single integer as parameter ( int ) and return nothing ( void ) and do not modify the contents of the class in anyway ( const )
*/

void executefunction ( int functionnumber, int inputforfunction )
{
	printf ( "%d\n", ( * functionpointers [ functionnumber ] ) ( inputforfunction ) ) ;
	// this line calls the function which is pointed ( * ) to by the functionnumber-th element of the functionpointers array which is a member of the object pointed to by the current object pointer ( this ) and passes the function the value of the variable inputforfunction as a parameter
}

int main ( void )
{
	functionpointers [ 0 ] = & square ;
	functionpointers [ 1 ] = & cube ;
	functionpointers [ 2 ] = & fourthpower ;
	functionpointers [ 3 ] = & squarepluscube ;
	functionpointers [ 4 ] = & squarepluscubeplusfourthpower ;
	
	int count ;
	for ( count = 0; count < 5; count ++ )
		executefunction ( count, 2 ) ;
}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-04 17:09 Function pointers to inline functions Shriramana Sharma
@ 2007-04-04 18:23 ` Glynn Clements
  2007-05-25  4:57   ` Shriramana Sharma
  2007-05-25  6:02   ` Shriramana Sharma
  2007-04-04 18:33 ` Steve Graegert
  1 sibling, 2 replies; 12+ messages in thread
From: Glynn Clements @ 2007-04-04 18:23 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming


Shriramana Sharma wrote:

> As per my understanding, an inline function is replaced in place by the 
> compiler with the body of the function, so it does not have a separate 
> location in memory in contrast with a regular function. This being so, 
> how is it possible to extract a pointer to an inline function and 
> effectively use it?
> 
> See the attached two examples. They work and though it's a good thing 
> for my project that I can extract a pointer to an inline function I do 
> not understand how it is possible.

If you declare a function as "inline", the compiler will typically add
a normal definition as well as inlining it. If you declare a function
as "static inline", the compiler may omit the normal definition.

Also, inlining is only performed if the corresponding optimisations
are enabled. Note the following gcc options:

`-fno-inline'
     Don't pay attention to the `inline' keyword.  Normally this option
     is used to keep the compiler from expanding any functions inline.
     Note that if you are not optimizing, no functions can be expanded
     inline.

`-finline-functions'
     Integrate all simple functions into their callers.  The compiler
     heuristically decides which functions are simple enough to be worth
     integrating in this way.

     If all calls to a given function are integrated, and the function
     is declared `static', then the function is normally not output as
     assembler code in its own right.

     Enabled at level `-O3'.

`-finline-limit=N'
     By default, GCC limits the size of functions that can be inlined.
     This flag allows the control of this limit for functions that are
     explicitly marked as inline (i.e., marked with the inline keyword
     or defined within the class definition in c++).  N is the size of
     functions that can be inlined in number of pseudo instructions
     (not counting parameter handling).  The default value of N is 600.
     Increasing this value can result in more inlined code at the cost
     of compilation time and memory consumption.  Decreasing usually
     makes the compilation faster and less code will be inlined (which
     presumably means slower programs).  This option is particularly
     useful for programs that use inlining heavily such as those based
     on recursive templates with C++.

     Inlining is actually controlled by a number of parameters, which
     may be specified individually by using `--param NAME=VALUE'.  The
     `-finline-limit=N' option sets some of these parameters as follows:

    `max-inline-insns-single'
          is set to N/2.

    `max-inline-insns-auto'
          is set to N/2.

    `min-inline-insns'
          is set to 130 or N/4, whichever is smaller.

    `max-inline-insns-rtl'
          is set to N.

     See below for a documentation of the individual parameters
     controlling inlining.

     _Note:_ pseudo instruction represents, in this particular context,
     an abstract measurement of function's size.  In no way, it
     represents a count of assembly instructions and as such its exact
     meaning might change from one release to an another.

`-fkeep-inline-functions'
     Even if all calls to a given function are integrated, and the
     function is declared `static', nevertheless output a separate
     run-time callable version of the function.  This switch does not
     affect `extern inline' functions.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-04 17:09 Function pointers to inline functions Shriramana Sharma
  2007-04-04 18:23 ` Glynn Clements
@ 2007-04-04 18:33 ` Steve Graegert
  2007-04-27 17:01   ` Shriramana Sharma
  2007-05-25  4:41   ` Shriramana Sharma
  1 sibling, 2 replies; 12+ messages in thread
From: Steve Graegert @ 2007-04-04 18:33 UTC (permalink / raw)
  To: linux-c-programming

Shriramana,

On 4/4/07, Shriramana Sharma <samjnaa@gmail.com> wrote:
> Hello.
>
> As per my understanding, an inline function is replaced in place by the
> compiler with the body of the function, so it does not have a separate
> location in memory in contrast with a regular function. This being so,
> how is it possible to extract a pointer to an inline function and
> effectively use it?
>
> See the attached two examples. They work and though it's a good thing
> for my project that I can extract a pointer to an inline function I do
> not understand how it is possible.

Whenever you request a pointer to an inline function the compiler will
place a normal subroutine version of the inline's implementation in an
object file and return its address.  So, effectively, the function
pointer does not point to an inline function at all.

       \Steve

--

Steve Grägert <steve@graegert.com>
Jabber    xmpp://graegerts@jabber.org
Internet  http://eth0.graegert.com, http://blog.graegert.com
-
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-04 18:33 ` Steve Graegert
@ 2007-04-27 17:01   ` Shriramana Sharma
  2007-05-04 13:40     ` Glynn Clements
  2007-05-25  4:41   ` Shriramana Sharma
  1 sibling, 1 reply; 12+ messages in thread
From: Shriramana Sharma @ 2007-04-27 17:01 UTC (permalink / raw)
  To: Linux C Programming List

[-- Attachment #1: Type: text/plain, Size: 1234 bytes --]

I did some experimentation with pointers to inline and static inline 
functions. Please unpack the attachment and run the build script.

You will observe that the nm files only differ in the last four lines, 
and that too in only three of them.

The difference is that the executable built from the source with just 
"inline" has the functions square, cube and fourthpower marked as "W" 
which according to man:nm means that "The symbol is a weak symbol that 
has not been specifically tagged as a weak object symbol".

In the same place, the executable built from the source with "static 
inline" has the same functions marked "t" which denotes a local symbol 
in the code section.

I actually expected static inline to make the entries for the functions 
disappear but OK, I'm calling pointers to those functions, so they won't 
disappear. But at least shouldn't they become weak objects, like they do 
for "inline"?

Though I do not profess to fully understand what a weak object is, (upon 
which matter I would like to learn more) it sounds like an object which 
does not have a full separate existence. If an inline function is such a 
weak object, how come a static inline one is not tagged as one?

Thanks.

Shriramana Sharma.

[-- Attachment #2: function-pointers-inline-staticinline.tar.gz --]
[-- Type: application/gzip, Size: 858 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-27 17:01   ` Shriramana Sharma
@ 2007-05-04 13:40     ` Glynn Clements
  0 siblings, 0 replies; 12+ messages in thread
From: Glynn Clements @ 2007-05-04 13:40 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: Linux C Programming List


Shriramana Sharma wrote:

> I did some experimentation with pointers to inline and static inline 
> functions. Please unpack the attachment and run the build script.
> 
> You will observe that the nm files only differ in the last four lines, 
> and that too in only three of them.
> 
> The difference is that the executable built from the source with just 
> "inline" has the functions square, cube and fourthpower marked as "W" 
> which according to man:nm means that "The symbol is a weak symbol that 
> has not been specifically tagged as a weak object symbol".
> 
> In the same place, the executable built from the source with "static 
> inline" has the same functions marked "t" which denotes a local symbol 
> in the code section.
> 
> I actually expected static inline to make the entries for the functions 
> disappear but OK, I'm calling pointers to those functions, so they won't 
> disappear. But at least shouldn't they become weak objects, like they do 
> for "inline"?

There's no point in making them weak if they're local.

> Though I do not profess to fully understand what a weak object is, (upon 
> which matter I would like to learn more) it sounds like an object which 
> does not have a full separate existence. If an inline function is such a 
> weak object, how come a static inline one is not tagged as one?

A weak symbol is one which is only used as a last resort. If another
library defines a non-weak version of the same symbol, it will be used
in preference to the weak version.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-04 18:33 ` Steve Graegert
  2007-04-27 17:01   ` Shriramana Sharma
@ 2007-05-25  4:41   ` Shriramana Sharma
  2007-05-25 22:45     ` Glynn Clements
  1 sibling, 1 reply; 12+ messages in thread
From: Shriramana Sharma @ 2007-05-25  4:41 UTC (permalink / raw)
  To: Steve Graegert; +Cc: linux-c-programming

Steve Graegert wrote:
> Whenever you request a pointer to an inline function the compiler will
> place a normal subroutine version of the inline's implementation in an
> object file and return its address.

Does this mean that the compiler will check the entire translation unit 
where the inline function is visible for pointer-request operations on 
the function and if any are present, the compiler will place a normal 
version in the object file?

This would mean that the function is output separately even if 
-finline-functions is used. Is that true?

Do I have a way of checking whether a function is output separately or 
not using nm? Do I just check to see whether the function name is there 
in the output or do I have to look for some flag on the function name? I 
am still not aware of the full depth of using nm.

Thanks as always,

Shriramana Sharma.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-04 18:23 ` Glynn Clements
@ 2007-05-25  4:57   ` Shriramana Sharma
  2007-05-25 22:41     ` Glynn Clements
  2007-05-25  6:02   ` Shriramana Sharma
  1 sibling, 1 reply; 12+ messages in thread
From: Shriramana Sharma @ 2007-05-25  4:57 UTC (permalink / raw)
  To: Glynn Clements; +Cc: linux-c-programming

Glynn Clements wrote:
> If you declare a function as "inline", the compiler will typically add
> a normal definition as well as inlining it. If you declare a function
> as "static inline", the compiler may omit the normal definition.

Would the static keyword in such a case also restrict the visibility of 
that inline function to that file only?

I mean, if I use -fkeep-inline-functions to get the function output in 
the object file, and if the static keyword also meant that the function 
is visible only in the translation unit in which it appears, then 
-fkeep-inline-functions would be rendered useless, since the only 
conceivable (to me) purpose of outputting a run-time callable version of 
an inline function is to make it available to callers from *outside the 
translation unit*, such as a programmer using a library.

(In fact, I think the *only* conceivable use-case would be someone using 
a library since another translation unit in the same project as the one 
containing the inline function can very well use the definition of the 
inline function to directly inline the code into the caller -- why would 
they want a separate runtime callable version in that case? So the only 
valid case is a programmer using a library but not having access to the 
actual definition of an inline function via the API.)

So I presume that when static is used with inline, it does not retain 
its meaning of "local to this translation unit". Am I right?

Shriramana Sharma.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-04-04 18:23 ` Glynn Clements
  2007-05-25  4:57   ` Shriramana Sharma
@ 2007-05-25  6:02   ` Shriramana Sharma
  1 sibling, 0 replies; 12+ messages in thread
From: Shriramana Sharma @ 2007-05-25  6:02 UTC (permalink / raw)
  To: Glynn Clements; +Cc: linux-c-programming

Glynn Clements wrote:
>      run-time callable version of the function.  This switch does not
>      affect `extern inline' functions.

What would be the purpose of "extern inline"?

I mean, inlining is done by the compiler, and extern is only useful to 
tell the linker to resolve references to a variable or function that is 
initially defined in another object file.

I tried putting an inline function *definition* in lib.cpp:

inline int foo ( void ) { return 2 ; }

and a *declaration* to that function qualified by extern inline in main.cpp:

# include <cstdio>
extern inline int foo ( void ) ;
int main ( void )
{
         printf ( "%d\n", foo () ) ;
}

The session transcript:

$ g++ -c main.cpp lib.cpp
main.cpp:3: warning: inline function ‘int foo()’ used but never defined
$ g++ -o main main.o lib.o
main.o: In function `main':
main.cpp:(.text+0x12): undefined reference to `foo()'
collect2: ld returned 1 exit status
$

So extern for inline functions does not work as for normal functions -- 
so what is the use of extern inline?

Shriramana Sharma.

-
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-05-25  4:57   ` Shriramana Sharma
@ 2007-05-25 22:41     ` Glynn Clements
  2007-05-29 13:03       ` Shriramana Sharma
  0 siblings, 1 reply; 12+ messages in thread
From: Glynn Clements @ 2007-05-25 22:41 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming


Shriramana Sharma wrote:

> > If you declare a function as "inline", the compiler will typically add
> > a normal definition as well as inlining it. If you declare a function
> > as "static inline", the compiler may omit the normal definition.
> 
> Would the static keyword in such a case also restrict the visibility of 
> that inline function to that file only?

A function can only actually be inlined in the translation unit
(source file plus any #include'd files) in which it occurs.

That's why you need "static inline" to eliminate the normal
definition. A non-static inline function has to have an implementation
in the object file so that it can be called from other object files.

> I mean, if I use -fkeep-inline-functions to get the function output in 
> the object file, and if the static keyword also meant that the function 
> is visible only in the translation unit in which it appears, then 
> -fkeep-inline-functions would be rendered useless, since the only 
> conceivable (to me) purpose of outputting a run-time callable version of 
> an inline function is to make it available to callers from *outside the 
> translation unit*, such as a programmer using a library.
> 
> (In fact, I think the *only* conceivable use-case would be someone using 
> a library since another translation unit in the same project as the one 
> containing the inline function can very well use the definition of the 
> inline function to directly inline the code into the caller

No, the compiler can only inline functions which are defined in the
same translation unit. Inlining requires source code, and the compiler
only has access to the source code for the current translation unit.

> -- why would 
> they want a separate runtime callable version in that case? So the only 
> valid case is a programmer using a library but not having access to the 
> actual definition of an inline function via the API.)
> 
> So I presume that when static is used with inline, it does not retain 
> its meaning of "local to this translation unit". Am I right?

No, "static" retains its original meaning.

There aren't many uses for -fkeep-inline-functions; the only one I can
think of right now is if you want to be able to call the function from
within a debugger (you can't call an inline function from a debugger).

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-05-25  4:41   ` Shriramana Sharma
@ 2007-05-25 22:45     ` Glynn Clements
  0 siblings, 0 replies; 12+ messages in thread
From: Glynn Clements @ 2007-05-25 22:45 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: Steve Graegert, linux-c-programming


Shriramana Sharma wrote:

> > Whenever you request a pointer to an inline function the compiler will
> > place a normal subroutine version of the inline's implementation in an
> > object file and return its address.
> 
> Does this mean that the compiler will check the entire translation unit 
> where the inline function is visible for pointer-request operations on 
> the function and if any are present, the compiler will place a normal 
> version in the object file?

Yes. A pointer to a function requires that the function actually
exists somewhere in the process' address space. Inline functions don't
"exist" in that sense.

> This would mean that the function is output separately even if 
> -finline-functions is used. Is that true?

Yes.

> Do I have a way of checking whether a function is output separately or 
> not using nm? Do I just check to see whether the function name is there 
> in the output or do I have to look for some flag on the function name? I 
> am still not aware of the full depth of using nm.

If the name appears in the output from "nm", then the function exists.
If it's inlined, it won't appear in the output from "nm".

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-05-25 22:41     ` Glynn Clements
@ 2007-05-29 13:03       ` Shriramana Sharma
  2007-06-04  7:08         ` Glynn Clements
  0 siblings, 1 reply; 12+ messages in thread
From: Shriramana Sharma @ 2007-05-29 13:03 UTC (permalink / raw)
  To: Glynn Clements; +Cc: linux-c-programming

Glynn Clements wrote:

>> I mean, if I use -fkeep-inline-functions to get the function output in 
>> the object file, and if the static keyword also meant that the function 
>> is visible only in the translation unit in which it appears, then 
>> -fkeep-inline-functions would be rendered useless, 

... in the case of static inline functions.

Is this correct or no?

Would a function visible only in its translation unit be accessible from 
a debugger, as you say? I would test it myself, but I haven't any idea 
how to load just a single object file in gdb and test it so I am asking.

Shriramana Sharma.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Function pointers to inline functions
  2007-05-29 13:03       ` Shriramana Sharma
@ 2007-06-04  7:08         ` Glynn Clements
  0 siblings, 0 replies; 12+ messages in thread
From: Glynn Clements @ 2007-06-04  7:08 UTC (permalink / raw)
  To: Shriramana Sharma; +Cc: linux-c-programming


Shriramana Sharma wrote:

> >> I mean, if I use -fkeep-inline-functions to get the function output in 
> >> the object file, and if the static keyword also meant that the function 
> >> is visible only in the translation unit in which it appears, then 
> >> -fkeep-inline-functions would be rendered useless, 
> 
> ... in the case of static inline functions.

Non-static inline functions are always generated so that they can be
called from other translation units. It's only when a function is both
static and inline that you can (normally) eliminate the function body
altogether.

> Is this correct or no?
> 
> Would a function visible only in its translation unit be accessible from 
> a debugger, as you say?

Yes.

The debugger might still require the function to be in scope (i.e. the
active stack frame must be in the same translation unit) in order to
call it, but that's down to how the debugger resolves symbols which
are entered by the user.

gdb doesn't have this requirement.

> I would test it myself, but I haven't any idea 
> how to load just a single object file in gdb and test it so I am asking.

Add a minimal main.c so that you can run it as a program.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2007-06-04  7:08 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-04 17:09 Function pointers to inline functions Shriramana Sharma
2007-04-04 18:23 ` Glynn Clements
2007-05-25  4:57   ` Shriramana Sharma
2007-05-25 22:41     ` Glynn Clements
2007-05-29 13:03       ` Shriramana Sharma
2007-06-04  7:08         ` Glynn Clements
2007-05-25  6:02   ` Shriramana Sharma
2007-04-04 18:33 ` Steve Graegert
2007-04-27 17:01   ` Shriramana Sharma
2007-05-04 13:40     ` Glynn Clements
2007-05-25  4:41   ` Shriramana Sharma
2007-05-25 22:45     ` Glynn Clements

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).