Parentheses in function calls

K

Kenny McCormack

Richard Harter said:
Yes and no. Within the narrow confines of the terminology of the
C standard,

Which, as everybody knows, is the only thing, repeat, the only thing,
that matters here. Everything else: irrelevant nonsense.
sizeof and + are indeed operators, a separate
category from functions, and never the twain shall meet.

Yup. That's the gospel here.

This is a very religious, orthodox group.

--
(This discussion group is about C, ...)

Wrong. It is only OCCASIONALLY a discussion group
about C; mostly, like most "discussion" groups, it is
off-topic Rorsharch [sic] revelations of the childhood
traumas of the participants...
 
F

Felix Palmen

* Richard Harter said:
Yes and no. Within the narrow confines of the terminology of the
C standard, sizeof and + are indeed operators, a separate
category from functions, and never the twain shall meet. From a
more general perspective operators are priveleged functions with
a specialized syntax.

No, they're not. You had to generalize to a level where you don't
consider the actual /call/ a characteristic of a function, and that just
doesn't make sense. Operators are different from function both in
language semantics and in compiler implementation. Even in the
mathematical view, there's a difference between
| a + b
and
| f: (a, b) -> a + b

The only exception you could possibly come up with are languages that
allow operator overloading where a user-defined function is "hidden"
behind an operator. This doesn't apply to C.

Regards, Felix
 
T

tm

No, they're not. You had to generalize to a level where you don't
consider the actual /call/ a characteristic of a function, and that just
doesn't make sense. Operators are different from function both in
language semantics and in compiler implementation.

I agree that operators differ from functions by their syntax.
Operators use priority and associativity while functions do not.

But the compiler implementation of operators and functions has
usually no influence on the semantics. While most compilers
implement operators with inline code this is not necessary.
Operators could also be implemented with subroutine calls and
functions could also be implemented with inline code (when no
recursion is involved).

Since I have implemented an interpreter and a compiler for a
language with operators and functions I can tell you that operators
really behave like functions with a specialized syntax.

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
I

Ian Collins

I agree that operators differ from functions by their syntax.
Operators use priority and associativity while functions do not.

But the compiler implementation of operators and functions has
usually no influence on the semantics. While most compilers
implement operators with inline code this is not necessary.
Operators could also be implemented with subroutine calls and
functions could also be implemented with inline code (when no
recursion is involved).

Since I have implemented an interpreter and a compiler for a
language with operators and functions I can tell you that operators
really behave like functions with a specialized syntax.

But not sizeof. No code is generated, the expression is always (with
the unique exception of VLAs) evaluated at compile time.
 
B

BartC

tm said:
I agree that operators differ from functions by their syntax.
Operators use priority and associativity while functions do not.

But the compiler implementation of operators and functions has
usually no influence on the semantics. While most compilers
implement operators with inline code this is not necessary.
Operators could also be implemented with subroutine calls and
functions could also be implemented with inline code (when no
recursion is involved).

Not as used in (standard) C. Which function corresponds to the '+' in a+b ?

There is some extra magic involved with operators that is not necessary for
functions. And that's apart from the totally different syntax.
 
T

tm

But not sizeof. No code is generated, the expression is always (with
the unique exception of VLAs) evaluated at compile time.

I know that sizeof is special, but it IMHO fits in my concept also.

When a compiler determines that an expression can be evaluated at
compile time (without disturbing side effects) it is free to do so.
Afterwards the compiler can use the result of the function instead.
The sizeof operator can also be viewed in this way. An expression
like

memcpy(dest, src, sizeof(char));

is probably equivalent to

memcpy(dest, src, 1);

So the code generated for sizeof is not a function call or an
inline expression, but code to load the constant 1 (which will be
used as parameter for memcpy).

When sizeof is used in a declaration it will not result in generated
code. But that does not contradict the concept that sizeof behaves
like a function (which can, with the exception of VLAs, be evaluated
at compile time).

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
I

Ian Collins

I know that sizeof is special, but it IMHO fits in my concept also.

When a compiler determines that an expression can be evaluated at
compile time (without disturbing side effects) it is free to do so.
Afterwards the compiler can use the result of the function instead.
The sizeof operator can also be viewed in this way. An expression
like

memcpy(dest, src, sizeof(char));

is probably equivalent to

memcpy(dest, src, 1);

It *is* equivalent. sizeof(char) is one by definition.
So the code generated for sizeof is not a function call or an
inline expression, but code to load the constant 1 (which will be
used as parameter for memcpy).

When sizeof is used in a declaration it will not result in generated
code. But that does not contradict the concept that sizeof behaves
like a function (which can, with the exception of VLAs, be evaluated
at compile time).

That fact that it is evaluated at compile time does make it a special
case. One can take the address of a function and use that to invoke the
function. That is not possible with an expression evaluated at compile
time. In fact sizeof doesn't behave at all at run time!
 
T

tm

Not as used in (standard) C. Which function corresponds to the '+' in a+b ?

I think you use the wrong concept here. I know that some languages
use a duality between a function and an operator. This is done to
introduce operator overloading (and user definable operator
symbols). But I think that such a duality is not a good idea.

IMHO there is no function which corresponds to '+'. The '+' itself
is the function. The '+' happens to be implemented by inline code.
That way it is not executed with a subroutine call. As you see I use
the term 'function' as logical concept while 'subroutine' refers to
a possible implementation of a function. Because of the inline
implementation of '+' you are not able to take the address of it.
A function without address is restricted in its use. An inline
function like '+' can be evaluated but it cannot be used where a
function pointer is needed. You can do

qsort(myArray, 100, sizeof(arrayElement), &myCompare);

but you cannot do

qsort(myArray, 100, sizeof(arrayElement), & + );

Such restrictions are also elsewhere. E.g.: register variables.
There is some extra magic involved with operators that is not necessary for
functions.

There is no extra magic involved with operators. At least my
understanding of them (and the implementation used in the Seed7
interpreter and compiler) works without extra magic.

If you still think that there is extra magic, please explain the
details with fewer magical words.

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
W

Willem

tm wrote:
) I know that sizeof is special, but it IMHO fits in my concept also.
)
) When a compiler determines that an expression can be evaluated at
) compile time (without disturbing side effects) it is free to do so.
) Afterwards the compiler can use the result of the function instead.
) The sizeof operator can also be viewed in this way.

No.
Consider the fact that sizeof takes a type, not a value.
Also consider that sizeof doesn't actually evaluate its argument.

A few trick questions:
does 'sizeof(i++)' increment i ?
does 'sizeof(i++ + i++)' invoke UB ?
(To be honest, I'm not sure to the answer of either of those.)


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

BartC

tm said:
I think you use the wrong concept here. I know that some languages
use a duality between a function and an operator. This is done to
introduce operator overloading (and user definable operator
symbols). But I think that such a duality is not a good idea.

IMHO there is no function which corresponds to '+'. The '+' itself
is the function. The '+' happens to be implemented by inline code.

The point is there are several possible 'functions' for '+', depending on
the type of the operands. That's because of overloading of some operators in
C, which doesn't happen with ordinary functions.
That way it is not executed with a subroutine call. As you see I use
the term 'function' as logical concept while 'subroutine' refers to
a possible implementation of a function.
Because of the inline
implementation of '+' you are not able to take the address of it.
A function without address is restricted in its use. An inline
function like '+' can be evaluated but it cannot be used where a
function pointer is needed. You can do

qsort(myArray, 100, sizeof(arrayElement), &myCompare);

but you cannot do

qsort(myArray, 100, sizeof(arrayElement), & + );

That's because there is some information missing: is this '+' to operate on
ints, doubles, or whatever? It would need to be, for example, &(+,int,int),
then there'd be no reason why the address of an equivalent function cannot
be arranged.
Such restrictions are also elsewhere. E.g.: register variables.


There is no extra magic involved with operators. At least my
understanding of them (and the implementation used in the Seed7
interpreter and compiler) works without extra magic.

If you still think that there is extra magic, please explain the
details with fewer magical words.

Overloading.
 
T

tm

It *is* equivalent. sizeof(char) is one by definition.

I try to formulate carefully, because there are so many nitpickers.
That fact that it is evaluated at compile time does make it a special
case.

And C even requires that sizeof is evaluated at compile time.
I have seen C compilers which try to evaluate other functions
like strlen() at compile time also. In this case strlen("")
was actually replaced by 0. I know that this can make problems
when you link with a library with its own implementation of
strlen()...
One can take the address of a function and use that to invoke the
function.

I have seen restrictions where some functions did not have an
address (because they are implemented with inline code). Does
C really grant that all functions have an address? C++ supports
the keyword inline (which suggests an inline implementation), but
AFAIK a function might be generated as well when the address of
the function is used. Otherwise C++ inline functions would not have
an address like register variables.
That is not possible with an expression evaluated at compile
time.

AFAIK Algol 68 had the concept of proceduring. This concept allowed
to turn a constant (possibly compile time evaluated) value into a
procedure (function) which returned just that value. That way it is
possible to use a (possibly compile time evaluated) constant at a
place where a function address is required. The compiler would
generate a function which just returns the constant value. I know
that C does not use the concept of proceduring. :)
In fact sizeof doesn't behave at all at run time!

AFAIK with the exception of VLAs.

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
I

Ian Collins

And C even requires that sizeof is evaluated at compile time.
I have seen C compilers which try to evaluate other functions
like strlen() at compile time also. In this case strlen("")
was actually replaced by 0. I know that this can make problems
when you link with a library with its own implementation of
strlen()...

That is fine, the compiler is free to do that, the difference is it is
not obliged to.
I have seen restrictions where some functions did not have an
address (because they are implemented with inline code). Does
C really grant that all functions have an address? C++ supports
the keyword inline (which suggests an inline implementation), but
AFAIK a function might be generated as well when the address of
the function is used. Otherwise C++ inline functions would not have
an address like register variables.

The same rule applies to C inline functions.
 
T

tm

The point is there are several possible 'functions' for '+', depending on
the type of the operands. That's because of overloading of some operators in
C, which doesn't happen with ordinary functions.

I probably work too much with languages where everything can be
overloaded. :) In my mind both, a function name and an operator
symbol are ambiguous. For me a function name alone or an operator
symbol alone are just pseudocode. They both need to be resolved with
(the types and access rights of) actual parameters. Sorry for the
inaccuracy. I should have said that the operator

(int) + (int)

is the function. This is again pseudocode, since C does not have
such a notation.
That's because there is some information missing: is this '+' to operate on
ints, doubles, or whatever? It would need to be, for example, &(+,int,int),
then there'd be no reason why the address of an equivalent function cannot
be arranged.

Yes. In case of '(int) + (int)' a implementation could normally
use inline code, but when the address is required a real function
could be provided also.
Overloading.

Ok.
As I explained above: For me overloading is not something special to
operators. So I excluded it from my reasoning.

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
T

tm

tm wrote:

) I know that sizeof is special, but it IMHO fits in my concept also.
)
) When a compiler determines that an expression can be evaluated at
) compile time (without disturbing side effects) it is free to do so.
) Afterwards the compiler can use the result of the function instead.
) The sizeof operator can also be viewed in this way.

No.
Consider the fact that sizeof takes a type, not a value.

This goes beyond C, but I can describe such things also. The concept
of an attribute parameter is helpful here. An attribute parameter
allows the attachment of a function or constant to a type. For
sizeof that would mean that sizeof is a constant which is overloaded
for all types (strange, but in my world constants can have
parameters also). Since C does not provide attribut parameters I can
only show this concept in Seed7:

const integer: sizeof (attr char) is 1;
const integer: sizeof (attr short) is 2;
const integer: sizeof (attr int) is 4;
const integer: sizeof (attr long) is 8;

Beyond attribute parameters Seed7 supports also types as parameters.
So sizeof with a type parameter could be seen also as some
built-in function where the header would look like (again in
Seed7 since C does lack type parameters):

const func integer: sizeof (in type: aType) is ...
Also consider that sizeof doesn't actually evaluate its argument.

Not all arguments are automatically evaluated. The right arguments
of the && and || operators are also not automatically evaluated
(the body of a 'while' statement is also such an example).
Technically such non-evaluated parameters are called closures.
The function decides to evaluate such parameters (even multiple
evaluations are possible). This way closure parameters allow
functions which emulate control structures. C does not provide
closure parameters for user defined functions, but other
languages support this concept. As such sizeof could take a
closure parameter which is never evaluated:

const integer: sizeof (in func char) is 1;
const integer: sizeof (in func short) is 2;
const integer: sizeof (in func int) is 4;
const integer: sizeof (in func long) is 8;
A few trick questions:
does 'sizeof(i++)' increment i ?

With the concept of a closure parameter (see above): NO
does 'sizeof(i++ + i++)' invoke UB ?

With closure parameters: NO, because the parameter is not evaluated.
(To be honest, I'm not sure to the answer of either of those.)

For actual C compilers I guess the answer is also NO
(I have not the time to try this out).

Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
E

Eric Sosman

Function, builtin, your splitting hares!

Long ago I knew a smart and talented person named Clough.
No relation, obviously.
My discussion is: you just need to establish precedence and associativity
for calling a function just like all other operators.

You call that a "discussion?" Pfui. I call it "plonk."
 
F

Felix Palmen

I'm quite sure that your text is clear to you, but it isn't
to me. Below I have asked for clarification at various points.

Nice try, but obviously you just don't /want/ to understand it. So, EOD
here.
 
K

Keith Thompson

Ian Collins said:
On 08/29/10 08:52 PM, tm wrote: [...]
memcpy(dest, src, sizeof(char));

is probably equivalent to

memcpy(dest, src, 1);

It *is* equivalent. sizeof(char) is one by definition.
[...]

An utterly irrelevant quibble:

In C90, if the declaration for memcpy() is not visible, the latter
invokes undefined behavior because memcpy() expects a size_t argument
and you're giving it an int.
 
N

Nick Keighley

Eric Sosman writes:

Function, builtin, your splitting hares!

ITYM "you're splitting hairs"

return is part of the syntax. It doesn't take parameters and it
doesn't return a value.

sizeof employs special magic which means it can be evaluated at
compile time (with a solitary exception mentioned else-thread). In
fact the information it needs is only available at compile time. It
also does some really screwy things compared with a function

sizeof (1/0)

is well defined because it doesn't evaluate its "argument" but only
looks at the type
My discussion is: you just need to establish precedence and associativity
for calling a function just like all other operators.

which means we have to learn the precedence table just to unscramble
the code.

You aren't going to talk people round. Either stick with perl (because
you like it) or write your own version of C. gcc is public domain you
hack it however you like (though it does have a reputation for being
difficult). Be aware when you've finished you don't have C anymore.

Perhaps a preprocessor that converts your sytax to C would suit you?

Some languages use more brackets, their users seem fairly happy

(set distance (sqrt (+ (* dx dx) (* dy dy))))

They don't need any precedence or associativity
 
J

John Bode

One possible problem with C as compared to other languages like Perl or
Shell is that function calls require parentheses which leads to cluttered
code. (But there are some funny exceptions in the standard library
though, eg return and size_of do not need parentheses)

It might be worthwhile for you to read up on parsing in general, LR
parsers in particular, and take a look at the C language grammar
(available at http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf,
Appendix A). If nothing else, it will illustrate why `return` and
`sizeof` are not "funny exceptions", but rather something completely
different from function calls.
Why not allow Juxtaposition to denote a functioncall with parentheses
only needed to override other laws of precedence? Seems to me it would be
easy to implement this and it would lead to cleaner code.

Yours Tony

Before commenting on the following statement, read up on the comma
operator in C (section 6.5.17 in the PDF linked above).

x = F (i + j) * k, y;

Does F take one or two parameters? Is the comma serving as an
argument separator (in which case F takes two arguments) or as a comma
operator (in which case F takes one argument)? If it's acting as the
comma operator, then which of the following sequences of operations is
the right one:

(i + j) * k is evaluted, y is evaluated, result of y is passed to
F,
result of F(y) is assigned to x
F(i + j) * k is evaluated, y is evaluated, result of y is assigned
to x

Or, even better:

x = F;

Does x get the result of calling F with no arguments, or does x get
the *address* of F?

And it turns out that it's *not* easy to implement; the grammar and
associated parser become more complicated because now you've
introduced some ambiguity in the expression (and remember that
precedence and associativity rules are products of the grammar;
ambiguity in the grammar means ambiguity in those rules). In the last
example above, the compiler can't decide whether to generate a
function call or simply assign the value of F to x until after it's
checked the types of both. Even then, it may not be able to guess
correctly.

Yes, there are languages that don't require parens for function
arguments; those languages are not C. You could not retrofit that
capability into C without either adding a *lot* of complexity to the
parser or by redefining the language grammar completely. For what
turns out to be not a whole lot of benefit.
 

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,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top