Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   inline vs. function pointers (http://www.velocityreviews.com/forums/t742671-inline-vs-function-pointers.html)

copx 01-27-2011 07:38 AM

inline vs. function pointers
 
C99 gave us the "inline" keyword and IIRC in standard C
(as opposed to certain propriety dialects) it is just a hint
for the compiler i.e. there is no guarantee that a function
declared "inline" will actually be inlined all the time.

Now, here is the problem, a certain C compiler when evoked
in ANSI C mode produces an error message when I put
pointers to "inline" functions in an array of function pointers.
The compiler actually inlines the function code in this case, never
putting the functions themselves in the resulting binary and
thus renders the pointers invalid.

Is that standard conforming behavior? I mean, is there a
rule that you are not allowed to use pointers to "inline" functions?



Eric Sosman 01-27-2011 02:10 PM

Re: inline vs. function pointers
 
On 1/27/2011 2:38 AM, copx wrote:
> C99 gave us the "inline" keyword and IIRC in standard C
> (as opposed to certain propriety dialects) it is just a hint for the
> compiler i.e. there is no guarantee that a function
> declared "inline" will actually be inlined all the time.
>
> Now, here is the problem, a certain C compiler when evoked
> in ANSI C mode produces an error message when I put
> pointers to "inline" functions in an array of function pointers.
> The compiler actually inlines the function code in this case, never
> putting the functions themselves in the resulting binary and
> thus renders the pointers invalid.
>
> Is that standard conforming behavior? I mean, is there a
> rule that you are not allowed to use pointers to "inline" functions?


Could you show a short (but complete and accurate!) sample
of the source code? And could you also exhibit the compiler's
complaint, instead of just describing it as "an error message?"

--
Eric Sosman
esosman@ieee-dot-org.invalid

dSpam@arcor.de 01-27-2011 02:22 PM

Re: inline vs. function pointers
 
On 27 Jan., 08:38, "copx" <c...@gazeta.pl> wrote:
> Now, here is the problem, a certain C compiler when evoked
> in ANSI C mode produces an error message when I put
> pointers to "inline" functions in an array of function pointers.
> The compiler actually inlines the function code in this case, never
> putting the functions themselves in the resulting binary and
> thus renders the pointers invalid.
>
> Is that standard conforming behavior? I mean, is there a
> rule that you are not allowed to use pointers to "inline" functions?


The answer to the first question depends on the function's linkage.
The answer to the second question is "No".

copx 01-27-2011 03:20 PM

Re: inline vs. function pointers
 


"Eric Sosman" wrote in message
news:ihrud5$vnm$1@news.eternal-september.org...
>Could you show a short (but complete and accurate!) sample
>of the source code?


See below.

>And could you also exhibit the compiler's
>complaint, instead of just describing it as "an error message?"


Ok.

===== test.c =======

#include <stdio.h>

#define FIB_MAX 8000

typedef unsigned char BYTE;
typedef void (* const LSYSTEM[3])(BYTE **);

static void ls_init(BYTE *p) { *p = 1; *(p + 1) = 0; }
static inline void ls0(BYTE **p) { **p = 0; }
static inline void ls1(BYTE **p) { **p = 2; *p += 1;}
static inline void ls2(BYTE **p) { **p = 1; *p += 1; ls1(p);}


static BYTE Ls[2][FIB_MAX];


static unsigned int lsystem(unsigned int n)
{
BYTE *cur, *pre;
unsigned int dp = 0;

ls_init(Ls[0]);

do {
pre = Ls[dp]; cur = Ls[dp = !dp];

do {
static LSYSTEM l = {ls0, ls1, ls2};

l[*pre](&cur);

} while (*pre++);

} while (--n);

return cur - Ls[dp];
}


unsigned int fib(unsigned int n)
{
return n < 2 ? n : lsystem(--n);
}


int main(void)
{
unsigned int i;

for (i = 0; i < 21; i++) printf("F%u: %u\n", i, fib(i));

return 0;
}

========

gcc -Wall -Wextra -std=c99 -pedantic -O2 test.c
No warnings, compiles and runs as expected.

I suspect the compiler who chokes on this is buggy, but I am not
sure. Here's the output:

===
Warning d:\dev\test\test.c: 28 assignment of pointer to inline
function(pointer to pointer to unsigned char) to pointer to
void function(pointer to pointer to unsigned char)

Warning d:\dev\test\test.c: 28 assignment of pointer to inline
function(pointer to pointer to unsigned char) to pointer to
void function(pointer to pointer to unsigned char)

Warning d:\dev\test\test.c: 28 assignment of pointer to inline
function(pointer to pointer to unsigned char) to pointer to
void function(pointer to pointer to unsigned char)

Error test.obj: Undefined (*UND*). Symbol _ls0
=======

Putting "inline" in the LSYSTEM typedef eliminates the
warnings but not the error. Oh, and GCC seems to think "inline"
has no place in a typedef:

test.c:6:30: warning: typedef 'LSYSTEM' declared 'inline'

Good thing I don't usually use C99, so I don't have to worry
about such disagreements. This was just some experimental
code.


Keith Thompson 01-27-2011 07:14 PM

Re: inline vs. function pointers
 
"copx" <copx@gazeta.pl> writes:
[...]
> Putting "inline" in the LSYSTEM typedef eliminates the
> warnings but not the error. Oh, and GCC seems to think "inline"
> has no place in a typedef:
>
> test.c:6:30: warning: typedef 'LSYSTEM' declared 'inline'


I believe gcc is correct. "inline" is a function specifier (the only
one in the language).

C99 6.7.4p2:

Function specifiers shall be used only in the declaration of an
identifier for a function.

In other words, "inline" isn't part of the function type; it's an
attribute of an individual declared function.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

copx 01-28-2011 07:01 AM

Re: inline vs. function pointers
 


"copx" wrote in message news:ihr7ej$irp$1@speranza.aioe.org...
>>The compiler actually inlines the function code in this case, never
>>putting the functions themselves in the resulting binary and
>>thus renders the pointers invalid.
>>
>>Is that standard conforming behavior?


Answering my own question again: No.

C99 6.7.4
function specifier:
inline

"Likewise, the function has a single address, regardless of the number of
inline deï¬nitions that occur"

Oh well, another bug report.


jacob navia 01-28-2011 07:37 AM

Re: inline vs. function pointers
 
Le 27/01/11 16:20, copx a écrit :
>
>
> "Eric Sosman" wrote in message
> news:ihrud5$vnm$1@news.eternal-september.org...
>> Could you show a short (but complete and accurate!) sample
>> of the source code?

>
> See below.
>
>> And could you also exhibit the compiler's
>> complaint, instead of just describing it as "an error message?"

>
> Ok.
>
> ===== test.c =======
>
> #include <stdio.h>
>
> #define FIB_MAX 8000
>
> typedef unsigned char BYTE;
> typedef void (* const LSYSTEM[3])(BYTE **);
>
> static void ls_init(BYTE *p) { *p = 1; *(p + 1) = 0; }
> static inline void ls0(BYTE **p) { **p = 0; }
> static inline void ls1(BYTE **p) { **p = 2; *p += 1;}
> static inline void ls2(BYTE **p) { **p = 1; *p += 1; ls1(p);}
>
>
> static BYTE Ls[2][FIB_MAX];
>
>
> static unsigned int lsystem(unsigned int n)
> {
> BYTE *cur, *pre;
> unsigned int dp = 0;
>
> ls_init(Ls[0]);
>
> do {
> pre = Ls[dp]; cur = Ls[dp = !dp];
>
> do {
> static LSYSTEM l = {ls0, ls1, ls2};
>
> l[*pre](&cur);
>
> } while (*pre++);
>
> } while (--n);
>
> return cur - Ls[dp];
> }
>
>
> unsigned int fib(unsigned int n)
> {
> return n < 2 ? n : lsystem(--n);
> }
>
>
> int main(void)
> {
> unsigned int i;
>
> for (i = 0; i < 21; i++) printf("F%u: %u\n", i, fib(i));
>
> return 0;
> }
>
> ========
>
> gcc -Wall -Wextra -std=c99 -pedantic -O2 test.c
> No warnings, compiles and runs as expected.
>
> I suspect the compiler who chokes on this is buggy, but I am not
> sure. Here's the output:
>
> ===
> Warning d:\dev\test\test.c: 28 assignment of pointer to inline
> function(pointer to pointer to unsigned char) to pointer to
> void function(pointer to pointer to unsigned char)
>


Assigning function pointers with different characteristics will
always produce a warning.


>
> Error test.obj: Undefined (*UND*). Symbol _ls0



static inline functions generate no function address.
If you want the function address eliminate the static...

> =======
>
> Putting "inline" in the LSYSTEM typedef eliminates the
> warnings but not the error. Oh, and GCC seems to think "inline"
> has no place in a typedef:
>
> test.c:6:30: warning: typedef 'LSYSTEM' declared 'inline'
>
> Good thing I don't usually use C99, so I don't have to worry
> about such disagreements. This was just some experimental
> code.
>


I do not see what C99 has to do with this here. Anyway. I will wait
till the next standard appears to fix those bugs. Maybe they will
declare that optional... :-)


jacob navia 01-28-2011 10:43 AM

Re: inline vs. function pointers
 
Le 28/01/11 08:54, Ian Collins a écrit :
> On 01/28/11 08:37 PM, jacob navia wrote:
>> Le 27/01/11 16:20, copx a écrit :
>>> ========
>>>
>>> gcc -Wall -Wextra -std=c99 -pedantic -O2 test.c
>>> No warnings, compiles and runs as expected.
>>>
>>> I suspect the compiler who chokes on this is buggy, but I am not
>>> sure. Here's the output:
>>>
>>> ===
>>> Warning d:\dev\test\test.c: 28 assignment of pointer to inline
>>> function(pointer to pointer to unsigned char) to pointer to
>>> void function(pointer to pointer to unsigned char)
>>>

>>
>> Assigning function pointers with different characteristics will
>> always produce a warning.

>
> But they don't have different types.
>

Yes but they have different characteristics: one is inline and the other
is not inline.

This warning is crucial when you have _stdcall functions. And
_stdcall is a similar attribute like inline.

>>> Error test.obj: Undefined (*UND*). Symbol _ls0

>>
>> static inline functions generate no function address.
>> If you want the function address eliminate the static...

>
> Says who?
>


Me.

> All the standard says is "Making a function an inline function suggests
> that calls to the function be as fast as possible".
>

Yes, and I do not generate the code for it. Changing it is around
4-5 hours work including testing. I will do it when the next standard
appears, to be sure that inline is not declared optional.



copx 01-28-2011 10:46 AM

Re: inline vs. function pointers
 


"jacob navia" wrote in message news:ihtrol$a0k$1@speranza.aioe.org...
>Assigning function pointers with different characteristics will
>always produce a warning.


But the pointers aren't different because the function specifier
("inline") is not supposed to be part of the function pointer type.

All the following functions..

static inline void foo(void);
static void foo(void);
inline void foo(void);

... have the same function pointer type: void (*)(void)

... at least in ISO C.

>> Error test.obj: Undefined (*UND*). Symbol _ls0

>
>static inline functions generate no function address.


Is lcc a ISO C compiler or not? Because a conforming compiler
cannot simply decide that "static inline functions generate
no function address". IMO the standard is pretty clear about
the fact that you aren't allowed to optimize away the function
definitions here.

>> Good thing I don't usually use C99, so I don't have to worry
>> about such disagreements. This was just some experimental
>> code.

>
>I do not see what C99 has to do with this here.


The point is that IMO the behavior of your compiler does not
conform to the C99 standard here and I haven't had such problems
with C90 code yet. That standard is fully supported by basically
every piece of software which calls itself "a C compiler". C99
unfortunately isn't.

>Anyway. I will wait till the next standard appears to fix those bugs.
>Maybe they will declare that optional... :-)


Your choice, cannot say I care much about this. I have just checked,
there aren't any big claims of conforming to ANY C standard
on the lccwin32 website, so it's ok I guess.

I can see why you want to stick to the current behavior. This
guaranteed inlining / function elemination behavior turns
static inline functions into full, type safe replacements for many
preprocessor macros. Also, not dealing with this particular
case (pointers to static inline functions) in a conforming way
probably simplifies the compiler logic.

I prefer ISO C compilers, though.


jacob navia 01-28-2011 11:04 AM

Re: inline vs. function pointers
 
Le 28/01/11 11:46, copx a écrit :
>
>
> "jacob navia" wrote in message news:ihtrol$a0k$1@speranza.aioe.org...
>> Assigning function pointers with different characteristics will
>> always produce a warning.

>
> But the pointers aren't different because the function specifier
> ("inline") is not supposed to be part of the function pointer type.
>
> All the following functions..
>
> static inline void foo(void);
> static void foo(void);
> inline void foo(void);
>
> .. have the same function pointer type: void (*)(void)
>
> .. at least in ISO C.
>


Yes, they have the same type.

But

int _stdcall fn(void);
and
int fn(void);

have also the same type but if you mix pointers to one with pointers to
the other a crash is guaranteed. So I always warn.

OK, I could spend hours "fixing" that warning and detecting that the
pointers are different because of the inline attribute and NOT because
of a _stdcall attribute or _noreturns or others.

Maybe one day I will do it, but before I have to do the correction for
the bad code generation that you pointed out. I am working already
6 hours in that problem and there is no solution in sight. I discovered
that if you write

dp = !dp;
ptr = table[dp];

the bug disappears. It is only when you write

ptr = table[dp = !dp];

that the bug manifests itself (only when optimizations are on).
And I will have for X hours more, I do not know.


> Your choice, cannot say I care much about this. I have just checked,
> there aren't any big claims of conforming to ANY C standard
> on the lccwin32 website, so it's ok I guess.
>
> I can see why you want to stick to the current behavior. This
> guaranteed inlining / function elemination behavior turns
> static inline functions into full, type safe replacements for many
> preprocessor macros. Also, not dealing with this particular case
> (pointers to static inline functions) in a conforming way
> probably simplifies the compiler logic.
>


Well, yes. I would have to detect when a function pointer is being
used. Then, realize that it is a pointer to an inline function. Then
I would have to add some annotation to the inline function pointer
symbol to generate ts code anyway.

WITHOUT INTRODUCING ANY NEW BUGS...

This is something like 1 day of work...

> I prefer ISO C compilers, though.
>


I have been working for this project for 12 years or more. I have
financed all expenses and all my work. But I can't do more than what I
do now. If you would buy a maintenance contract you would be served
quickly. But you didn't.

jacob


All times are GMT. The time now is 10:42 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57