473,399 Members | 2,278 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

Passing a pointer to a function to the function it points to

I've been doing this sort of thing, and I want to know if it's a
sensible way to act (I think this is correct and portable, but want to
make sure):

int f(int a, void(*b)())
{
static int x=0;
if(x) return a;
x=1;
/* do something with a */
((void(*)(int, void(*)()))b)(a,b);
x=0;
return a;
}

Is this one of the few cases where a cast is actually necessary? The
idea is that b should be of the same type as f, so it can be called
with itself as an argument, but there's no way to write that directly
with a finitely-long prototype. One solution might be to do without
prototypes (I'm not sure if that would work), but I don't really want
to do that. So the other solution's to use a pointer of the wrong
type; void* can't be used because it might not be able to represent a
function pointer, so I used void(*)() (should I have used void(*)
(void) instead?). Is this the right, portable way to go about this? (I
don't write code like (void(*)(int, void(*)())) very often.) Likewise,
is my static int the best way to go about preventing an infinite
regress? (The semantics of the situation are that I want the function
to just return a if it's called a second time from within itself.)

--
ais523

Oct 1 '07 #1
8 1255
ais523 <ai****@bham.ac.ukwrites:
I've been doing this sort of thing, and I want to know if it's a
sensible way to act (I think this is correct and portable, but want to
make sure):

int f(int a, void(*b)())
{
static int x=0;
if(x) return a;
x=1;
/* do something with a */
((void(*)(int, void(*)()))b)(a,b);
x=0;
return a;
}
I suspect you have undefined behaviour here. I have not picked though
the standard to be sure but casts like this often work despite a
disclaimer that they are not guaranteed to work.
Is this one of the few cases where a cast is actually necessary? The
idea is that b should be of the same type as f, so it can be called
with itself as an argument, but there's no way to write that directly
with a finitely-long prototype.
No indeed. Though if a typedef name became defined earlier than it
does one could:

typedef int ftype(int, ftype *); /* not legal */

Anyway, to be *sure* you have no UB, I think you need something like
this:

#include <stdio.h>
#include <stdarg.h>

typedef int Function(int, ...);

int f(int a, ...)
{
if (a == 1)
return a;
else {
Function *fp;
va_list ap;
va_start(ap, a);
fp = va_arg(ap, Function *);
va_end(ap);
return a * fp(a - 1, fp);
}
}

int main(void)
{
printf("5! = %d\n", f(5, f));
return 0;
}

Sorry not to have picked over all you questions, but I suspect the
answer to all the cast-based solutions is UB.

--
Ben.
Oct 1 '07 #2
On Mon, 01 Oct 2007 07:09:31 -0700, ais523 wrote:
I've been doing this sort of thing, and I want to know if it's a
sensible way to act (I think this is correct and portable, but want to
make sure):

int f(int a, void(*b)())
{
static int x=0;
if(x) return a;
x=1;
/* do something with a */
((void(*)(int, void(*)()))b)(a,b);
x=0;
return a;
}

Is this one of the few cases where a cast is actually necessary?
No. You can omit the cast entirely:

int f(int a, void(*b)())
{
static int x=0;
if(x) return a;
x=1;
/* do something with a */
b(a,b);
x=0;
return a;
}

b is declared as a pointer to a function having an unspecified number of
parameters, not as having no parameters. There are some subtleties; you
can't do this if the type of a is short instead of int, for example, but
in the example you gave, it's fine this way.
Oct 1 '07 #3
ais523 wrote:
I've been doing this sort of thing, and I want to know if it's a
sensible way to act (I think this is correct and portable, but want to
make sure):

int f(int a, void(*b)())
{
static int x=0;
if(x) return a;
x=1;
/* do something with a */
((void(*)(int, void(*)()))b)(a,b);
x=0;
return a;
}

Is this one of the few cases where a cast is actually necessary?
I can't see why in the world you would think so. The IOCCC line
((void(*)(int, void(*)()))b)(a,b);
can be perfectly well written
b(a,b);

Oct 1 '07 #4
On Oct 1, 9:46 pm, Martin Ambuhl <mamb...@earthlink.netwrote:
ais523 wrote:
I've been doing this sort of thing, and I want to know if it's a
sensible way to act (I think this is correct and portable, but want to
make sure):
int f(int a, void(*b)())
{
static int x=0;
if(x) return a;
x=1;
/* do something with a */
((void(*)(int, void(*)()))b)(a,b);
x=0;
return a;
}
Is this one of the few cases where a cast is actually necessary?

I can't see why in the world you would think so. The IOCCC line
((void(*)(int, void(*)()))b)(a,b);
can be perfectly well written
b(a,b);
The problem here, from my view, is that b happens to point to a
function that was declared with a prototype, yet it's of a datatype
that says that the function is a K&R-style prototypeless one. Can you
call a prototyped function through a prototypeless pointer?
--
ais523

Oct 2 '07 #5
ais523 wrote:
(The semantics of the situation are that I want the function
to just return a if it's called a second time from within itself.)
Why?

I mean, how did you come to this interesting state? I've never had to
diddle around temporarily suppressing a possible recursion like that;
I wonder if there's some more straightforward solution to whatever
your actual problem is.

--
Chris "standing in his boots" Dollin

Hewlett-Packard Limited Cain Road, Bracknell, registered no:
registered office: Berks RG12 1HN 690597 England

Oct 2 '07 #6
On Tue, 02 Oct 2007 05:16:17 -0700, ais523 wrote:
On Oct 1, 9:46 pm, Martin Ambuhl <mamb...@earthlink.netwrote:
>I can't see why in the world you would think so. The IOCCC line
> ((void(*)(int, void(*)()))b)(a,b);
can be perfectly well written
b(a,b);

The problem here, from my view, is that b happens to point to a function
that was declared with a prototype, yet it's of a datatype that says
that the function is a K&R-style prototypeless one. Can you call a
prototyped function through a prototypeless pointer?
So long as it's a function that could be defined without a prototype, it
doesn't matter whether it actually is.

This means

void f1() {}
void f2(void) {}
void f3(c) char c; {}
void f4(char c) {}
void f5(i) int i; {}
void f6(int i) {}
void f7(int i, ...) {}

char c = 'a';
int i = 1;

int main(void) {
void (*fp)();

fp = f1; fp(); // this is fine
fp = f2; fp(); // this is fine
fp = f3; fp(c); // this is fine
fp = f4; fp(c); // this is not fine
fp = f5; fp(i); // this is fine
fp = f6; fp(i); // this is fine
fp = f7; fp(i); // this is not fine
}

f4 and f7 cannot be defined without a function prototype, so they cannot
be called without a function prototype. The rest can be (or are) defined
without one, so they can be called without one.

If you try to compile this program, you will probably notice that your
compiler complains about the lines that are not fine. In this case, so
long as you don't add casts, it's safe to trust the compiler on which
functions are fine and which aren't.
Oct 2 '07 #7
On Oct 2, 3:24 pm, Chris Dollin <chris.dol...@hp.comwrote:
ais523 wrote:
(The semantics of the situation are that I want the function
to just return a if it's called a second time from within itself.)

Why?

I mean, how did you come to this interesting state? I've never had to
diddle around temporarily suppressing a possible recursion like that;
I wonder if there's some more straightforward solution to whatever
your actual problem is.
I was implementing a spec which specifically had the 'suppress
recursion' as a special case, I think as a method of preventing an
infinite loop if there were errors upstream.
--
ais523

Oct 4 '07 #8
ais523 wrote:
On Oct 2, 3:24 pm, Chris Dollin <chris.dol...@hp.comwrote:
>ais523 wrote:
(The semantics of the situation are that I want the function
to just return a if it's called a second time from within itself.)

Why?

I mean, how did you come to this interesting state? I've never had to
diddle around temporarily suppressing a possible recursion like that;
I wonder if there's some more straightforward solution to whatever
your actual problem is.

I was implementing a spec which specifically had the 'suppress
recursion' as a special case, I think as a method of preventing an
infinite loop if there were errors upstream.
Bizarre. Oh, well, if you're stuck with it, you're stuck with it.

--
Chris "seeking solvent" Dollin

Hewlett-Packard Limited registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

Oct 4 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: harry | last post by:
I have an object that's passed in to a function as a parameter i.e public boolean getProjectTitle(ProjectHeader_DTO obj) {...} If I then call a method on this object inside the function i.e...
5
by: Newsgroup - Ann | last post by:
Gurus, I have the following implementation of a member function: class A { // ... virtual double func(double v); void caller(int i, int j, double (* callee)(double)); void foo() {caller(1,...
58
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of...
11
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to...
11
by: John Pass | last post by:
Hi, In the attached example, I do understand that the references are not changed if an array is passed by Val. What I do not understand is the result of line 99 (If one can find this by line...
17
by: Christopher Benson-Manica | last post by:
Does the following program exhibit undefined behavior? Specifically, does passing a struct by value cause undefined behavior if that struct has as a member a pointer that has been passed to...
1
by: Shawn | last post by:
As if it won't be clear enough from my code, I'm pretty new to C programming. This code is being compiled with an ANSI-C compatible compiler for a microcontroller. That part, I believe, will be...
6
by: Roman Mashak | last post by:
Hello, I belive the reason of problem is simple, but can't figure out. This is piece of code: struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };
7
by: TS | last post by:
I was under the assumption that if you pass an object as a param to a method and inside that method this object is changed, the object will stay changed when returned from the method because the...
6
by: virgincita schmidtmann | last post by:
Good evening, I would like to pass the size of an array from the commandline. int main(int argc, int *argv) { .... max=*argv; int list; ....
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.