Weird bit of code-- legal???

A

Ancient_Hacker

A while back I had to recompile some old code, originally written by a
really good programmer, but one prone to use every trick in the book,
and then some.

There was a statement, something like this:


Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C? It compiled with an Microsoft C 2.6 or so compiler, but
of course that isnt much help.
 
G

gbostock

Ancient_Hacker said:
A while back I had to recompile some old code, originally written by a
really good programmer, but one prone to use every trick in the book,
and then some.

There was a statement, something like this:


Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C? It compiled with an Microsoft C 2.6 or so compiler, but
of course that isnt much help.

This code is really quite simple and shouldn't give a decent C
programmer any problems whatsoever.

The line is basically a function call that puts the result in Result.
Depending on the value of Mode (is it 2?) it will invoke the function
pointed to by TwoWayFunc or FourWayFunc; passing the Params 1 through
3.

Why shouldn't it be legal and why would it cause any head scratching?
 
A

Ancient_Hacker

This code is really quite simple and shouldn't give a decent C
programmer any problems whatsoever.

The line is basically a function call that puts the result in Result.
Depending on the value of Mode (is it 2?) it will invoke the function
pointed to by TwoWayFunc or FourWayFunc; passing the Params 1 through
3.

Why shouldn't it be legal and why would it cause any head scratching?


.... because I didnt mention, the function names are just that-- not
variables holding the function addresses. I did not know you could
use raw function names in a conditional expression. Then again, I
didnt know and I suspect a lot of folks don't know that the thing
before the parameters is an actual "expression".
 
F

Frederick Gotham

Ancient_Hacker posted:
Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C?


Not to boast, but I understood the line of code at first glance.

"TwoWayFunc" and "FourWayFunc" are pressumably both function pointers of the
same type.

"Mode == 2" is evaluated, and depending on the result, either of the
functions is called with the arguments, "Param1, Param2, Param3".

The return value of the function call is stored in "Result".

The code is perfectly legal.
 
F

Frederick Gotham

Ancient_Hacker posted:
... because I didnt mention, the function names are just that-- not
variables holding the function addresses. I did not know you could
use raw function names in a conditional expression.


When you use the name of a function on its own (i.e. without parenthese after
it which contain arguments), then what you have is the address of that
function.

For instance, let's define a function:

void Func1(void) {}

Now let's create a pointer to a function of that type:

void (*p)(void);

Now let's store the address of Func1 in p:

p = Func1;

The expression "Func1" in the above is the address of the function.
 
K

Kenny McCormack

There was a statement, something like this:


Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C? It compiled with an Microsoft C 2.6 or so compiler, but
of course that isnt much help.

This code is really quite simple and shouldn't give a decent C
programmer any problems whatsoever.[/QUOTE]

It is not a question of "understanding" it or whether or not it works on
any given implementation. As you well know, both of those topics are OT
in this ng.

Rather, it is a question of whether or not it is "strictly conforming",
according to the gods of the ng. I remember reading here sometime back
that there are some funky rules regarding "?:" expressions in the
standard - of the usual sort, that is, that allow to fail things that
obviously should work and which do work on most-if-not-all implementations.

And which are thus, by the rules of the NG,
OT/non-portable/wrong/can't-discuss-here/blah-blah-blah.
 
A

Ancient_Hacker

Frederick said:
Not to boast, but I understood the line of code at first glance.

"TwoWayFunc" and "FourWayFunc" are pressumably both function pointers of the
same type.

That's the funny thing, they're not ptrs. They're the raw function
names. I'd never seen conditional expressions used in that particular
context.
 
J

jmcgill

Ancient_Hacker said:
That's the funny thing, they're not ptrs.

Doesn't that make them constant pointers? Or are they different?

Thumbing through K&R2 to try to answer this myself.
 
N

Nelu

Ancient_Hacker said:
That's the funny thing, they're not ptrs. They're the raw function
names. I'd never seen conditional expressions used in that particular
context.

C99, 6.3.2 Other operands
4. A function designator is an expression that has function type.
Except when it is the
operand of the sizeof operator or the unary & operator, a
function designator with
type ‘‘function returning type’’ is converted to an expression
that has type ‘‘pointer to
function returning type’’.
 
K

Kenneth Brody

Kenny said:
This code is really quite simple and shouldn't give a decent C
programmer any problems whatsoever.

It is not a question of "understanding" it or whether or not it works on
any given implementation. As you well know, both of those topics are OT
in this ng.

Rather, it is a question of whether or not it is "strictly conforming",
according to the gods of the ng. I remember reading here sometime back
that there are some funky rules regarding "?:" expressions in the
standard - of the usual sort, that is, that allow to fail things that
obviously should work and which do work on most-if-not-all implementations.

And which are thus, by the rules of the NG,
OT/non-portable/wrong/can't-discuss-here/blah-blah-blah.[/QUOTE]

What's OT? What's non-portable? What's wrong? What's non-discussable
here?

Now, the post is missing the definitions for all referenced names, but
assuming that TwoWayFunc and FourWayFunc are functions (or pointers to
functions) with the same prototype, there's nothing wrong here.

And, given that the OP's question was basically "is this legal C, or
an extension to this particular compiler", I would say that the OP is
100% on-topic.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Keith Thompson

Ancient_Hacker said:
A while back I had to recompile some old code, originally written by a
really good programmer, but one prone to use every trick in the book,
and then some.

There was a statement, something like this:


Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C? It compiled with an Microsoft C 2.6 or so compiler, but
of course that isnt much help.

Yes, assuming TwoWayFunc and FourWayFunc are functions of the same
type, and that the parameter list is valid for both.

Expressions of function type (not pointer-to-function type, function
type) are treated similarly to expressions of array type. An
expression of function type (such as the name of a function) is
implicitly converted to a pointer to the function, unless it's the
operand of a unary "sizeof" or "&" operator. (If it's the operand of
sizeof, it's a constraint violation; this rule makes "sizeof func"
illegal rather than an expression that yields the size of a function
pointer. If it's the operand of "&", the result is the address of the
function, the same result you'd get without the "&".)

An ordinary function call:
func(arg1, arg2)
invokes the function call operator. The left operand must be a
pointer-to-function. The conversion of "func" to a pointer occurs
before the function call operator is evaluated.

If func_ptr is an object of type pointer-to-function then this:
func_ptr(arg1, arg2)
works the same way, except that no implicit conversion was done on the
left operand.

In your expression, if TwoWayFunc and FourWayFunc are function names,
they're both implicitly converted to function pointers. The
expression ( Mode == 2 ? TwoWayFunc : FourWayFunc ) is evaluated
normally, and the result (either a pointer to TwoWayFunc or a pointer
to FourWayFunc) is used as the left operand of the function call
operator.

Once you understand how function names are handled, and how the
function call operator works, it's all perfectly straightforward.
 
K

Keith Thompson

Kenneth Brody said:
Kenny McCormack wrote:
[the usual]
What's OT? What's non-portable? What's wrong? What's non-discussable
here?

Kenny McCormack is a self-proclaimed troll. Please ignore him. I
recommend killfiling him; you won't miss anything useful or
interesting.
 
K

Kenneth Brody

Keith said:
Kenneth Brody said:
Kenny McCormack wrote:
[the usual]
What's OT? What's non-portable? What's wrong? What's non-discussable
here?

Kenny McCormack is a self-proclaimed troll. Please ignore him. I
recommend killfiling him; you won't miss anything useful or
interesting.

Yes, but at least his "blah blah blah" posts are usually in response
to things that could be considered OT.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Kenny McCormack

It is not a question of "understanding" it or whether or not it works on
any given implementation. As you well know, both of those topics are OT
in this ng.

Rather, it is a question of whether or not it is "strictly conforming",
according to the gods of the ng. I remember reading here sometime back
that there are some funky rules regarding "?:" expressions in the
standard - of the usual sort, that is, that allow to fail things that
obviously should work and which do work on most-if-not-all implementations.

And which are thus, by the rules of the NG,
OT/non-portable/wrong/can't-discuss-here/blah-blah-blah.

What's OT? What's non-portable? What's wrong? What's non-discussable
here?[/QUOTE]

The phrases (which I myself introduced):
obviously should work and which do work on most-if-not-all implementations.
Now, the post is missing the definitions for all referenced names, but
assuming that TwoWayFunc and FourWayFunc are functions (or pointers to
functions) with the same prototype, there's nothing wrong here.

And, given that the OP's question was basically "is this legal C, or
an extension to this particular compiler", I would say that the OP is
100% on-topic.

Oh, I agree. I wasn't saying that the post was OT. I was saying that
what the OP was trying to get at was: Is it legal C or is it OT (I.e.,
happens to work on my implementation).

Oh, and pay no attention to the real trolls here - the so-called regs
who go into a tizzy every time I post. They're harmless once you get
used to it.
 
S

Snis Pilbor

Ancient_Hacker said:
A while back I had to recompile some old code, originally written by a
really good programmer, but one prone to use every trick in the book,
and then some.

There was a statement, something like this:


Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C? It compiled with an Microsoft C 2.6 or so compiler, but
of course that isnt much help.

IMHO function decay is one of the most beautiful things in all of C.
For one thing, and many people don't realize this, it practically makes
C object oriented, in the hands of a skilful user. In fact, it allows
all the benefits of object orientation without any of the drawbacks. :)
 
O

Old Wolf

Kenneth said:
Now, the post is missing the definitions for all referenced names, but
assuming that TwoWayFunc and FourWayFunc are functions (or pointers to
functions) with the same prototype, there's nothing wrong here.

The functions don't have to have prototypes; this is accepted
by my compiler:

int foo();
int bar(int x) { return 0; }

int main()
{
return (0 ? foo : bar)(1);
}

int foo() { }

In fact, this is also accepted and runs correctly, although I'm not
sure how well-defined it is:

#include <stdio.h>

int foo();

int bar(char *x) {
printf("bar: %p\n", x);
return 0;
}

int main()
{
return (getchar() == 'x' ? foo : bar)(0);
}

int foo(int x) {
printf("foo: %d\n", x);
return 0;
}
 
J

jaysome

A while back I had to recompile some old code, originally written by a
really good programmer, but one prone to use every trick in the book,
and then some.

There was a statement, something like this:


Result = ( Mode == 2 ? TwoWayFunc : FourWayFunc ) ( Param1,
Param2, Param3 );

... after a little headscratching I figured it out, but ... is this
legal in C? It compiled with an Microsoft C 2.6 or so compiler, but
of course that isnt much help.

This is equivalent to:

if ( Mode == 2 )
{
Result = TwoWayFunc(Param1, Param2, Param3);
}
else
{
Result = FourWayFunc(Param1, Param2, Param3);
}

The original "really good programmer" bit off more than he could chew,
from the standpont if understandability and maintainability, as the
equivalent code should not cause your head to scratch at all.

In the world of safety critical software, which I deal with on a
regular basis, we have no tolerance for such code as that written by
the "really good programmer". He or she either changes it or he or she
is out the door. No if, ands, or but about it.

Best regards
 
C

Chris Dollin

Ancient_Hacker said:
That's the funny thing, they're not ptrs. They're the raw function
names.

(fx:blink) Yes, which decay to pointers in just about any legal context.

I suppose C /could/ have been defined to require using &functionName to
get the associated pointer. Let us be thankful for small mercies.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top