Casting function pointers

N

Nudge

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;
}
 
B

Ben Pfaff

Nudge said:
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.
 
W

Walter Roberson

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".
 
M

Mabden

Nudge said:
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"
 
J

Joe Estock

Ben said:
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[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
> \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\
> );}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 ;)
 
B

Ben Pfaff

Joe Estock said:
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.
 
G

Grumble

Ben said:
Nudge 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:

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
 
B

Ben Pfaff

Grumble said:
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.)
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top