By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,433 Members | 1,842 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,433 IT Pros & Developers. It's quick & easy.

Casting function pointers

P: n/a
Hello everyone,

Does the following code invoke undefined behavior?

In other words, is it dangerous to lie to the compiler about a
function's return type, when the return type is the same size or
smaller than sizeof(int).

It seems to me there could be platforms where
char = 8 bits, short = 16 bits, int = 32 bits,
and, on that hypothetical platform, chars, shorts, and ints
might be stored in different registers altogether?
int printf(const char *format, ...);

typedef int fp_t(void);

int f1(void)
{
register int res = -1;
return res;
}

short f2(void)
{
register short res = -2;
return res;
}

signed char f3(void)
{
register signed char res = -3;
return res;
}

void foo(fp_t fp)
{
printf("%d\n", fp());
}

int main(void)
{
foo(f1);
foo((fp_t *)f2);
foo((fp_t *)f3);
return 0;
}

--
Regards, Nudge
Nov 15 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
In article <43***********************@news.free.fr>,
Nudge <ho******@kma.eu.org> wrote:
In other words, is it dangerous to lie to the compiler about a
function's return type, when the return type is the same size or
smaller than sizeof(int). It seems to me there could be platforms where
char = 8 bits, short = 16 bits, int = 32 bits,
and, on that hypothetical platform, chars, shorts, and ints
might be stored in different registers altogether?


Correct. You cannot presume anything about how values of different
sizes are returned, or even about values of the same size (e.g.,
float vs int) that are not specifically defined as being
compatible.

If I recall correctly, the standard does define some compatibilities,
mostly having to do with type qualifiers such as "const".
--
Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us. -- Ecclesiastes
Nov 15 '05 #2

P: n/a
Nudge <ho******@kma.eu.org> writes:
Does the following code invoke undefined behavior?
Yes.
In other words, is it dangerous to lie to the compiler about a
function's return type, when the return type is the same size or
smaller than sizeof(int).
Yes.
It seems to me there could be platforms where
char = 8 bits, short = 16 bits, int = 32 bits,
and, on that hypothetical platform, chars, shorts, and ints
might be stored in different registers altogether?


Yes. A related situation occurs on x86, where functions might
return `char' values in the AL 8-bit register. If the caller
expects to receive 32 bits it will read EAX, a 32-bit register
that contains AL as its least significant 8 bits. The most
significant 24 bits of the return value can then be any arbitrary
value.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 15 '05 #3

P: n/a
"Nudge" <ho******@kma.eu.org> wrote in message
news:43***********************@news.free.fr...
Hello everyone,

Does the following code invoke undefined behavior?

In other words, is it dangerous to lie to the compiler about a
function's return type, when the return type is the same size or
smaller than sizeof(int).

It seems to me there could be platforms where
char = 8 bits, short = 16 bits, int = 32 bits,
and, on that hypothetical platform, chars, shorts, and ints
might be stored in different registers altogether?


"It seems to me there could be platforms where char = 8 bits, short = 16
bits, int = 32 bits, and, on that hypothetical platform, chars, shorts,
and ints might be stored in different registers"
Nov 15 '05 #4

P: n/a
Ben Pfaff wrote:
Nudge <ho******@kma.eu.org> writes:

Does the following code invoke undefined behavior?

Yes.

In other words, is it dangerous to lie to the compiler about a
function's return type, when the return type is the same size or
smaller than sizeof(int).

Yes.

It seems to me there could be platforms where
char = 8 bits, short = 16 bits, int = 32 bits,
and, on that hypothetical platform, chars, shorts, and ints
might be stored in different registers altogether?

Yes. A related situation occurs on x86, where functions might
return `char' values in the AL 8-bit register. If the caller
expects to receive 32 bits it will read EAX, a 32-bit register
that contains AL as its least significant 8 bits. The most
significant 24 bits of the return value can then be any arbitrary
value.
int main(void){char

p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\ \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\ );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof > p-1;putchar(p[i]\ );}return 0;}


One of these days I'll compile your signature and figure out what in the
world it does. I've seen it enough that it's starting to bother me now ;)

Nov 15 '05 #5

P: n/a
Joe Estock <je*****@NOSPAMnutextonline.com> writes:
One of these days I'll compile your signature and figure out what in the
world it does. I've seen it enough that it's starting to bother me now ;)


For what it's worth, I actually have two different compilable
signatures.
--
"When in doubt, treat ``feature'' as a pejorative.
(Think of a hundred-bladed Swiss army knife.)"
--Kernighan and Plauger, _Software Tools_
Nov 15 '05 #6

P: n/a
Ben Pfaff wrote:
Nudge wrote:

Does the following code invoke undefined behavior?

Yes.

In other words, is it dangerous to lie to the compiler about a
function's return type, when the return type is the same size or
smaller than sizeof(int).

Yes.

It seems to me there could be platforms where
char = 8 bits, short = 16 bits, int = 32 bits,
and, on that hypothetical platform, chars, shorts, and ints
might be stored in different registers altogether?

Yes. A related situation occurs on x86, where functions might
return `char' values in the AL 8-bit register. If the caller
expects to receive 32 bits it will read EAX, a 32-bit register
that contains AL as its least significant 8 bits. The most
significant 24 bits of the return value can then be any arbitrary
value.


As a matter of fact, I was thrown off by GCC's behavior on Linux/x86:

f1:
movl $-1, %eax
ret
f2:
movl $-2, %eax
cwtl
ret
f3:
movb $-3, %al
movsbl %al,%eax
ret

I thought there might be a good reason for GCC to insist on widening the
result to 32 bits in f2 and f3. (I imagined some kind of integral
promotion rule might come into play?)

Nudge
Nov 17 '05 #7

P: n/a
Grumble <de*****@kma.eu.org> writes:
Ben Pfaff wrote:
Yes. A related situation occurs on x86, where functions might
return `char' values in the AL 8-bit register. If the caller
expects to receive 32 bits it will read EAX, a 32-bit register
that contains AL as its least significant 8 bits. The most
significant 24 bits of the return value can then be any arbitrary
value.
As a matter of fact, I was thrown off by GCC's behavior on Linux/x86:


[...where f3() returns signed char...]
f3:
movb $-3, %al
movsbl %al,%eax
ret

I thought there might be a good reason for GCC to insist on widening the
result to 32 bits in f2 and f3. (I imagined some kind of integral
promotion rule might come into play?)


The System V ABI for i386 actually says that scalar return values
go in EAX. It doesn't say anything about using only AX or AL for
`short' or `char'. I imagine that it's because of this very
issue. (That's why I said "might": other ABIs for i386 could be
different, but I'm only familiar with the System V ABI.)
--
Just another C hacker.
Nov 17 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.