Global restricted function pointer

J

Jacob Shamalini

How do I declare a global restricted pointer to a function?

I have a vanilla global

void (*fp)();

But if I try

void (*restrict fp)();

it's an "invalid use of restrict" (GCC with -std=c99 -pedantic).
What's the correct syntax? Or is this legal in the first place?
 
I

Igmar Palsenberg

Jacob said:
void (*restrict fp)();

it's an "invalid use of restrict" (GCC with -std=c99 -pedantic).
What's the correct syntax? Or is this legal in the first place?

I doubt it's legal. What are you trying to accomplish ?



Igmar
 
J

Jacob Shamalini

I doubt it's legal. What are you trying to accomplish ?

Igmar

I have a trampoline variable into which I repeatedly load callbacks
for execution, I'd like to be hopeful about it getting optimized into
a register.

More or less like this:

void (*current_callback)();

void run()
{
for(;;)
current_callback(); // each callback loads a new callback as a
side effect
}


I _can_ declare a global restricted object pointer, therefore I wonder
if a function pointer might be legal.

Jacob
 
J

James Kuyper

Jacob said:
How do I declare a global restricted pointer to a function?

I have a vanilla global

void (*fp)();

But if I try

void (*restrict fp)();

What 'restrict' means is that all accesses to the object pointed at by
the restrict-qualified pointer use, directly or indirectly, the value of
that particular pointer. The C standard doesn't define any permitted
method for accessing the memory that a function pointer points at, only
a method for calling the function that the pointer points at. The
'restrict' qualifier therefore cannot be meaningfully applied to
pointers to functions, which is why the standard specifies â€Types other
than pointer types derived from object or incomplete types shall not be
restrict-qualified.†(6.7.3p2)

Whatever it is that you're really trying to do, this is not the correct
way to do it.
 
T

Thomas Maier-Komor

Jacob said:
I have a trampoline variable into which I repeatedly load callbacks
for execution, I'd like to be hopeful about it getting optimized into
a register.

More or less like this:

void (*current_callback)();

void run()
{
for(;;)
current_callback(); // each callback loads a new callback as a
side effect
}


I _can_ declare a global restricted object pointer, therefore I wonder
if a function pointer might be legal.

Jacob

Could it be that you confused restrict with volatile? If you want to
prevent the compiler from assuming current_callback is always the same,
then you need to define it as
void (*volatile current_callback)(void);

In contrast, the keyword restrict tells the compiler that two pointers
point at areas that don't overlap...

HTH,
Thomas
 
J

Jacob Shamalini

What 'restrict' means is that all accesses to the object pointed at by
the restrict-qualified pointer use, directly or indirectly, the value of
that particular pointer. The C standard doesn't define any permitted
method for accessing the memory that a function pointer points at, only
a method for calling the function that the pointer points at. The
'restrict' qualifier therefore cannot be meaningfully applied to
pointers to functions, which is why the standard specifies â€Types other
than pointer types derived from object or incomplete types shall not be
restrict-qualified.†(6.7.3p2)

Whatever it is that you're really trying to do, this is not the correct
way to do it.

Ok, I see. Thanks a lot.

Jacob
 
J

Jacob Shamalini

Jacob Shamalini schrieb:












Could it be that you confused restrict with volatile? If you want to
prevent the compiler from assuming current_callback is always the same,
then you need to define it as
void (*volatile current_callback)(void);

In contrast, the keyword restrict tells the compiler that two pointers
point at areas that don't overlap...

HTH,
Thomas

No, more likely I'm just confused in general :) Thanks, though.

What I'd _really_ want is a global register variable, like this:

void (*register fp)();

But that I can't have, that much I know. So I was thinking in my
feeble little mind that restrict might do the same/sameish thing, but
now I begin to think I'm actually not grasping the whole restrict
concept yet.

Jacob
 
W

Willem

Jacob Shamalini wrote:
) I have a trampoline variable into which I repeatedly load callbacks
) for execution, I'd like to be hopeful about it getting optimized into
) a register.
)
) More or less like this:
)
) void (*current_callback)();
)
) void run()
) {
) for(;;)
) current_callback(); // each callback loads a new callback as a
) side effect
) }
)
)
) I _can_ declare a global restricted object pointer, therefore I wonder
) if a function pointer might be legal.

I don't think 'restrict' does what you think it does.
And even if it did, you do *not* want it optimized into a register,
otherwise it could be calling the wrong function.

If you *want* it to be a register instead of a global pointer,
the following method could be useful:

void run()
{
void *(* cb)();
cb = init;
while (cb)
cb = cb();
}

I.E. each callback returns the next callback instead of
setting it in a global.

Note: the type definition of cb becomes quite tricky in this case,
so I decided to let the functions return void pointers which get
autoconverted to the correct function type by the assignment.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

Jacob Shamalini

If you *want* it to be a register instead of a global pointer,
the following method could be useful:

void run()
{
  void *(* cb)();
  cb = init;
  while (cb)
    cb = cb();

}

I.E. each callback returns the next callback instead of
setting it in a global.

Ah, yes, I see. That seems sensible. Thanks a lot.

Jacob
 
B

Ben Bacarisse

Jacob Shamalini wrote:
) I have a trampoline variable into which I repeatedly load callbacks
) for execution, I'd like to be hopeful about it getting optimized into
) a register.
[snip]

If you *want* it to be a register instead of a global pointer,
the following method could be useful:

void run()
{
void *(* cb)();
cb = init;
while (cb)
cb = cb();
}

I.E. each callback returns the next callback instead of
setting it in a global.

Note: the type definition of cb becomes quite tricky in this case,
so I decided to let the functions return void pointers which get
autoconverted to the correct function type by the assignment.

But is that defined in C89?

It's not defined in C89 or C99.
I was under the impression that you
could safely convert function pointers from one function pointer to
another (assuming you get the type right)
Yes.

but not from function
pointer to void * and back. If my understanding is correct it's
okay in C99 but problematic in C89.

Mine is that it is not OK in either. The OP needs to pick a type for
the callback function and have a pointer to that type returned by all
of them.

<snip>
 
J

Jacob Shamalini

Jacob Shamalini wrote:
) I have a trampoline variable into which I repeatedly load callbacks
) for execution, I'd like to be hopeful about it getting optimized into
) a register.
[snip]

If you *want* it to be a register instead of a global pointer,
the following method could be useful:
void run()
{
 void *(* cb)();
 cb = init;
 while (cb)
   cb = cb();
}
I.E. each callback returns the next callback instead of
setting it in a global.
Note: the type definition of cb becomes quite tricky in this case,
so I decided to let the functions return void pointers which get
autoconverted to the correct function type by the assignment.

But is that defined in C89?  I was under the impression that you
could safely convert function pointers from one function pointer to
another (assuming you get the type right) but not from function
pointer to void * and back.  If my understanding is correct it's
okay in C99 but problematic in C89.  

Indeed, when I tried the above code, my compiler issued a warning,
with both C89 and C99.

No matter though, I got around it with some typedef and type casting
trickery:

typedef void (*fp)();

void run()
{
fp cb;

cb = init;
for (;;)
cb = ((fp (*)())cb)();
}

The above compiles on GCC, with -std=c99 -pedantic, -std=c89 -pedantic
and -ansi -pedantic (plus -W -Wall), without warnings.

Jacob
 
K

Keith Thompson

Jacob Shamalini said:
Jacob Shamalini wrote:
) I have a trampoline variable into which I repeatedly load callbacks
) for execution, I'd like to be hopeful about it getting optimized into
) a register.
[snip]

If you *want* it to be a register instead of a global pointer,
the following method could be useful:
void run()
{
 void *(* cb)();
 cb = init;
 while (cb)
   cb = cb();
}
I.E. each callback returns the next callback instead of
setting it in a global.
Note: the type definition of cb becomes quite tricky in this case,
so I decided to let the functions return void pointers which get
autoconverted to the correct function type by the assignment.

But is that defined in C89?  I was under the impression that you
could safely convert function pointers from one function pointer to
another (assuming you get the type right) but not from function
pointer to void * and back.  If my understanding is correct it's
okay in C99 but problematic in C89.  

Indeed, when I tried the above code, my compiler issued a warning,
with both C89 and C99.

No matter though, I got around it with some typedef and type casting
trickery:

typedef void (*fp)();

void run()
{
fp cb;

cb = init;
for (;;)
cb = ((fp (*)())cb)();
}

The above compiles on GCC, with -std=c99 -pedantic, -std=c89 -pedantic
and -ansi -pedantic (plus -W -Wall), without warnings.

If you use a cast, compilers tend to assume you know what you're doing
and shut up. But you're still invoking undefined behavior.

cb is declared as a pointer to a function returning void. You're
converting it (with a cast) to a pointer to a function returning a
pointer to a function returning void, and then doing a function call
via the converted function pointer. Calling a function using a type
other than the actual type of the function invokes UB.
 
W

Willem

Keith Thompson wrote:
) If you use a cast, compilers tend to assume you know what you're doing
) and shut up. But you're still invoking undefined behavior.
)
) cb is declared as a pointer to a function returning void. You're
) converting it (with a cast) to a pointer to a function returning a
) pointer to a function returning void, and then doing a function call
) via the converted function pointer. Calling a function using a type
) other than the actual type of the function invokes UB.

Anyway, I don't think it's UB because the function pointer gets
converted to another type, and then back to the original type.

I was under the impression that the same held for void pointers.
(I.E. converting to void pointer and then back to the original
function pointer type would be conormant.)

If not, how can a function return a pointer to itself without
invoking UB ? Preferrably without some horrid convoluted syntax ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Beej Jorgensen

Jacob Shamalini said:
cb = ((fp (*)())cb)();

The above compiles on GCC, with -std=c99 -pedantic, -std=c89 -pedantic
and -ansi -pedantic (plus -W -Wall), without warnings.

Amazingly it also goes through my LISP interpreter without a problem!

;)

-Beej
 
K

Keith Thompson

Willem said:
Keith Thompson wrote:
) If you use a cast, compilers tend to assume you know what you're doing
) and shut up. But you're still invoking undefined behavior.
)
) cb is declared as a pointer to a function returning void. You're
) converting it (with a cast) to a pointer to a function returning a
) pointer to a function returning void, and then doing a function call
) via the converted function pointer. Calling a function using a type
) other than the actual type of the function invokes UB.

Anyway, I don't think it's UB because the function pointer gets
converted to another type, and then back to the original type.

Perhaps I missed something among the masses of parentheses, but
I don't see a conversion back to the original type.

Here's the code in question:

| typedef void (*fp)();
|
| void run()
| {
| fp cb;
|
| cb = init;
| for (;;)
| cb = ((fp (*)())cb)();
| }

Now that I think about it, we haven't seen a declaration for init.
If init is either a function returning fp, or a pointer to such a
function, it might be ok.
I was under the impression that the same held for void pointers.
(I.E. converting to void pointer and then back to the original
function pointer type would be conormant.)

No, conversion between pointer-to-void and pointer-to-function is not
guaranteed to be meaningful. (Some real-world systems have function
pointers that are much bigger than void* pointers, so such conversions
could lose information.)
If not, how can a function return a pointer to itself without
invoking UB ? Preferrably without some horrid convoluted syntax ?

It can't directly return a pointer to itself, but you can pick an
arbitrary function type to be used as a generic function type, and
explicitly convert back and forth between the generic type and
whatever type you need. I'd use something like:

typedef void generic_function(void);

though some might prefer to typedef the pointer-to-function type
rather than the function type.

If the actual defined functions return pointers to fp, then the code
in question may be correct. Though I'd prefer not to use empty
parentheses, denoting an old-style function declaration with
unspecified parameters. In other words, I'd write:
typedef void (*fp)(void);
rather than
typedef void (*fp)();
 
J

jameskuyper

Willem said:
Keith Thompson wrote:
) If you use a cast, compilers tend to assume you know what you're doing
) and shut up. But you're still invoking undefined behavior.
)
) cb is declared as a pointer to a function returning void. You're
) converting it (with a cast) to a pointer to a function returning a
) pointer to a function returning void, and then doing a function call
) via the converted function pointer. Calling a function using a type
) other than the actual type of the function invokes UB.

Anyway, I don't think it's UB because the function pointer gets
converted to another type, and then back to the original type.

I was under the impression that the same held for void pointers.
(I.E. converting to void pointer and then back to the original
function pointer type would be conormant.)

"A pointer to void may be converted to or from a pointer to any
incomplete or object type. A pointer to any incomplete or object type
may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer." (6.3.2.3p1)

Notice that this guarantee is provided only for pointers to incomplete
or object types; there is no wording that provides comparable
guarantees for conversions between void* and pointers to function
types.
If not, how can a function return a pointer to itself without
invoking UB ? Preferrably without some horrid convoluted syntax ?

"A pointer to a function of one type may be converted to a pointer to
a function of another type and back again; the result shall compare
equal to the original pointer." (6.3.2.3p8)

Therefore, you can use any pointer type you want as a generic function
pointer type. There's no need for a special type like void*. For this
purpose I usually use the most minimal function type I can thing of:

#include <stdlib.h>
typedef void (*generic_fp)(void);

static generic_fp return_self(void)
{
return (generic_fp) return_self;
}

int main(void)
{
generic_fp fp1 = return_self();
generic_fp fp2 = (*(generic_fp(*)(void)) fp1)();

return fp1 == fp2 ? EXIT_SUCCESS : EXIT_FAILURE;
}
 
N

Nate Eldredge

Jacob Shamalini said:
I have a trampoline variable into which I repeatedly load callbacks
for execution, I'd like to be hopeful about it getting optimized into
a register.

More or less like this:

void (*current_callback)();

void run()
{
for(;;)
current_callback(); // each callback loads a new callback as a
side effect
}

As pointed out, `restrict' is not what you want. I'll point out that if
you want current_callback to be put in a register, some compilers
provide platform-specific extensions to do this. For GCC, which you
mentioned, see the section "Global Reg Vars" in the manual. Note there
are a variety of complications. For instance, you need to either choose
a register that is by default preserved across function calls, or
recompile all code in your program (including libraries) with an
appropriate option. And you will want to measure the performance of the
program before and after, since if registers were needed elsewhere, this
might make your code run slower. This is especially true on
register-starved machines like x86.
 
K

Kaz Kylheku

If not, how can a function return a pointer to itself without
invoking UB ? Preferrably without some horrid convoluted syntax ?

Yes. The circularity is established via self-reference by means
of incomplete struct:

struct funwrap {
struct funwrap (*pfunc)(void);
};

struct funwrap func(void)
{
struct funwrap self = { func };
return self;
}
 
S

Sjouke Burry

Kaz said:
Yes. The circularity is established via self-reference by means
of incomplete struct:

struct funwrap {
struct funwrap (*pfunc)(void);
};

struct funwrap func(void)
{
struct funwrap self = { func };
return self;
}
Is this C++ ?? (oh horror)....
 

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

Members online

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,630
Members
45,335
Latest member
Tommiesal

Latest Threads

Top