![]() |
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? |
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 |
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". |
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. |
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" |
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. |
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... :-) |
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. |
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. |
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.