Common misconceptions about C (C95)

I

Ioannis Vranos

Keith said:
I've worked in languages where some operator symbols are punctuation,
and some are keywords. Ada, for example, has "not", "and", "or",
"mod", "rem", "abs", and probably others. Writing "not(x)" rather
than "not x" would be silly. In Perl, the distinction between
operators and built-in functions is a bit blurry.


Just for information, C95 also provides keywords for unary and binary
operators with <iso646.h>.


So for example you can write:


#include <iso646.h>



int main(void)
{
int x=5, y= 4, a=0;

/* ... */


if(x> 1 and y< 2)
/* Do something. */

else
if(x> 10 or y> 10)
/* Do something else. */


if(not a)
/* Do something. */


return 0;
}




--
Ioannis Vranos

C95 / C++03 Software Developer

http://www.cpp-software.net
 
E

Eric Sosman

Kaz said:
C has other operators, like while, for, if, return, ...

Interesting. I tried to use the `return' operator

int alternatingOnesAndZeroes(void) {
static int previous = 0;
previous = return 1 - previous;
}

.... but the compiler blew its siren at me, pulled me over,
and cited me for a moving violation. I also tried the while'
operator, and the compiler gave me *another* ticket. I'm
afraid to try an expression with the `for' operator, since
there's a "three strikes" law that could send me to prison
as an habitual lawbreaker.

Are you saying my compiler is buggy, and is handing out
citations for perfectly valid code? What gives???
 
L

lawrence.jones

Keith Thompson said:
Perhaps C's mistake is having only *one* operator whose symbol looks
like an identifer. If C used "$" rather than "sizeof", this wouldn't
be an issue; similarly, if C had *more* operator keywords, "sizeof"
wouldn't be exceptional.

As of the last committee meeting, it now has "alignof", too.
 
E

Eric Sosman

Joe said:
Richard wrote:
[ snip ]
For sure. But I don't see how that has any impact on the fact that for
years voids have been used for holding "unsuitable" things. Joe Wright's
incredulous demand for a "citation" had me in stitches.
I'm OK providing entertainment. Can you provide an instance of a voids
holding anything at all?

There is no void type. There is however a void* type. I don't find where
a function pointer can be assigned to a variable of type void*. Do you?

There *is* a void type, saith 6.2.5p19:

The void type comprises an empty set of values; it is
an incomplete type that cannot be completed.

Since there are no values of type void, however, it is not
possible to have a void variable that holds one.

There is no guarantee that a function pointer can be converted
to or from a void* (or any other data pointer) "meaningfully."
That is, the converted pointer need not be usable, and converting
it back to the original type need not produce the original value
undamaged.
 
S

Sjouke Burry

Eric said:
Interesting. I tried to use the `return' operator

int alternatingOnesAndZeroes(void) {
static int previous = 0;
previous = return 1 - previous;
}

... but the compiler blew its siren at me, pulled me over,
and cited me for a moving violation. I also tried the while'
operator, and the compiler gave me *another* ticket. I'm
afraid to try an expression with the `for' operator, since
there's a "three strikes" law that could send me to prison
as an habitual lawbreaker.

Are you saying my compiler is buggy, and is handing out
citations for perfectly valid code? What gives???
The compiler should stop warning you and serve you with a ticket.
Tsssk. Much to lenient...
 
K

Kaz Kylheku

I quite agree that it is essential to understand that sizeof of
is an operator than an a function. I don't feel it is necessary
to use a coding style to reflect this distinction. YMMV.

If one takes a more general view, the distinction between
operands and functions is artificial. The operator/operand
business exists to regularize special syntax. One can just as
well say that in C operators are language defined functions with
a special syntax.

The peculiar thing about sizeof is not that it is an operator;
rather the peculiar thing is that it is reflective. That is, it
gives information about the code itself.

That was until variable length arrays.

All C operators have some reflective aspect, because it's a static
language.

For instance, no object is ever accessed without type information being pulled
out from the expression (i.e. a piece of the program) which is accessing it.

But sizeof on (a non-VLA) purely accesses only something known at compile time.

So do constant expressions, though. And for instance, the address of a static
object is a constant expression.

So code like this is also ``reflective'':

struct tree { struct tree *left, *right; const char *data; };

struct tree left_child = { 0, 0, "lc" };
struct tree right_child = { 0, 0, "rc" };
struct tree root = { &left_child, &right_child, "root" };

Here, &left_child and &right_child are constant expressions,
which is why we are permitted to use them as initializers
for static storage.

The literals "lc", "rc" and "root" are themselves reflective too; they are
piece of the program which become available to it as pieces of datum.
On the whole, C is not
a reflective language. This may explain why some C programmers
are not reflective. :).

In effect, sizeof is a hack, a way for the programmer to access
information that the compiler has.

It looks like a hack if you think that there should be a wall
between programmers and the compiler's information.
 
K

Kaz Kylheku

Interesting. I tried to use the `return' operator

int alternatingOnesAndZeroes(void) {
static int previous = 0;
previous = return 1 - previous;
}

Interesting, I tried to use the `cast' operator.

previous = (void) 0;

An operator is not as something that yields a value.
... but the compiler blew its siren at me, pulled me over,
and cited me for a moving violation. I also tried the while'
operator, and the compiler gave me *another* ticket. I'm
afraid to try an expression with the `for' operator, since
there's a "three strikes" law that could send me to prison
as an habitual lawbreaker.

If you don't like ``while'' being called ``operator'', do you have an
alternative?

It is a keyword. But ``char'' is a also a keyword; this is a lexical category,
not a semantic category. We have another name for ``char'' when it is
engaged in its semantic role, like ``type specifier''. We don't only
call it a keyword.

So, semantically, what is ``while''? It is not a statement, because a while
statement is the whole syntactic unit ``while ( expr ) statement ''.
We have terminology for other parts of the while statement: the expr is
a ``controlling expression'' and the statement is referred to as ``loop body''
defined in 6.8.5 in italics.

So that leaves ``while''. What is that?

If you have no name for the role that the keyword ``while'' plays in the while
statement, you have no basis for objecting to my calling it an operator.

Propose your alterative instead, and argue why it is better than extending
the term ``operator''.

The term already seems to do that, or is on practically on the verge.

It appears in italics in 6.4.6 Punctuators, where it is given a meaning
that appears not to exclude symbols like ``for'' and ``while''.

A punctuator is a symbol that has independent syntactic and semantic
significance. Depending on context, it may specify an operation to be
performed (which in turn may yield a value or a function designator,
produce a side effect, or some combination thereof) in which case it is
known as an <italics>operator</italics> (other forms of operator also exist
in some contexts). An operand is an entity on which an operator acts.

See, punctuators can be operators, but the set of operators is broader. We are
not given any specific closed list of symbols such that those are called
operators, and no others. Simply, an unspecified set of other forms may be
operators. Operators need not even be symbols. For instance cast operators are
combinations of symbols. Operators need not produce a value, and are
context-dependent.

Can someone make a convincing argument that while and return must
not be called operators?
 
R

Richard Tobin

Eric Sosman said:
The void type comprises an empty set of values;

Interesting that it has *no* values, since it could hold one
without requiring any space.

-- Richard
 
E

Eric Sosman

Kaz said:
Interesting, I tried to use the `cast' operator.

previous = (void) 0;

An operator is not as something that yields a value.


If you don't like ``while'' being called ``operator'', do you have an
alternative?

It is a keyword. But ``char'' is a also a keyword; this is a lexical category,
not a semantic category. We have another name for ``char'' when it is
engaged in its semantic role, like ``type specifier''. We don't only
call it a keyword.

So, semantically, what is ``while''? It is not a statement, because a while
statement is the whole syntactic unit ``while ( expr ) statement ''.
We have terminology for other parts of the while statement: the expr is
a ``controlling expression'' and the statement is referred to as ``loop body''
defined in 6.8.5 in italics.

So that leaves ``while''. What is that?

`while' is part of the syntax of two statement forms, referred
to informally as "the while statement" and "the do-while statement"
and described more rigorously by the grammar productions in 6.8.5.
Why should it need any further name than "part of the syntax?"

We know of "the ternary operator," but do we have separate terms
for the '?' and ':' tokens contribute to it? No, they're just part
of the syntax. We know how to put a label on a statement, but do we
have a special name for the ':' that goes after the label identifier?
No, it's just part of the syntax. We know that we must parenthesize
the controlling expression that follows `while' or `if' or `switch',
but do we have a special name for those parentheses? No, they're
just part of the syntax. What more is needed?
If you have no name for the role that the keyword ``while'' plays in the while
statement, you have no basis for objecting to my calling it an operator.

Throughout 6.5 and 6.10, the Standard lists various things and
calls them "operators." It does not apply the term to anything
else, so I believe the list should be regarded as comprehensive,
taken as complete.

In particular, the word "operator" appears nowhere in 6.8, not
even in the non-normative bits.
Propose your alterative instead, and argue why it is better than extending
the term ``operator''.

"Must every little keyword have a jargon all its own?" (With
apologies to Jerome Frank).

The `while' keyword -- and `for' and `if' and `return' and
others not mentioned -- are a part of the required syntax of the
statements in which they appear, that's all. We don't need a
special name for the white space that separates `int' from `main';
why should we need a special name for `while'?
The term already seems to do that, or is on practically on the verge.

It appears in italics in 6.4.6 Punctuators, where it is given a meaning
that appears not to exclude symbols like ``for'' and ``while''.

A punctuator is a symbol that has independent syntactic and semantic
significance. Depending on context, it may specify an operation to be
performed (which in turn may yield a value or a function designator,
produce a side effect, or some combination thereof) in which case it is
known as an <italics>operator</italics> (other forms of operator also exist
in some contexts). An operand is an entity on which an operator acts.

See, punctuators can be operators, but the set of operators is broader. We are
not given any specific closed list of symbols such that those are called
operators, and no others. Simply, an unspecified set of other forms may be
operators. Operators need not even be symbols. For instance cast operators are
combinations of symbols. Operators need not produce a value, and are
context-dependent.

Okay; the list of punctuators mentions that some of them are
operators, and mentions that some things not listed (non-punctuators)
are also operators. But it does not follow that everything not
listed is an operator! Would you describe the decimal constant 42
as an "operator," simply because it's not listed as a punctuator?
Or how about the aforementioned white-space "operator?"

(For an amusing sidelight, look up the Whitespace programming
language.)
Can someone make a convincing argument that while and return must
not be called operators?

My argument boils down to this: The Standard does not use the
term "operator" to refer to `while', so we shouldn't use it that
way either.
 
S

Stefan Ram

William Ahern said:
For instance in Java if you cast Foo to Object and then
Object to Bar, the language can detect the error.

This is no error in Java.

The following program compiles and runs without any error.

The last line features a cast of Alpha to Object and then
Object to Beta.

However, I have not used »*oo«, because this might be
derived from »*UBAR«, where the »F« comes from a word that
might be considered indecent or distracting by some readers.
Therefore, I have replaced »*oo« with »Alpha« and »*ar«
with »Beta«.

interface Alpha { public void alpha(); }

interface Beta { public void beta(); }

class Object implements Alpha, Beta
{ public void alpha(){} public void beta(){} }

public class Main
{ public static void main( final java.lang.String[] args )
{ final Alpha alpha = new Object();
( ( Beta )( Object )alpha ).beta(); }}
 
K

Kaz Kylheku

We know of "the ternary operator," but do we have separate terms
for the '?' and ':' tokens contribute to it?

Yes, they are punctuators. See 6.4.6. They serve a similar role to commas,
semicolons, parentheses and the like.

Speaking of which, the ( ) in the while statement are punctuators also.

See, we have names for everything.
of the syntax. We know how to put a label on a statement, but do we
have a special name for the ':' that goes after the label identifier?

Punctuator. In C99, fourth row, second from the left.
 
K

Keith Thompson

BTW if the, ah, operand might be a macro consider using
parentheses as a prophylactic.
[...]

If the operand is a macro, and the macro is defined in such a way that
parentheses are necessary, *fix the macro definition*.

I'd use prophylactic parentheses only if I *knew* that the particular
macro were poorly defined and I was unable to fix it.
 
K

Kenny McCormack

Nick Keighley said:
I've written code in C that was compiled with a C++ compiler. It
wasn't my idea but it goes on.

I'm quite familiar with an organization that used C/C++ for many years,
for all its mission critical work, without knowing which compiler (i.e.,
which language) they were using. So, it was very important to them to
write code that would compile (and compile correctly - i.e., the
resulting executable produce the right results) under either language.

This is because they were writing C, but compiling (unknowingly) with C++.
Further, since I know some nitpicker will try to claim that there is no
such language as "C/C++" (a term which I used in this post), let me
point out that these people really were programming in "C/C++".

This situation existed for many years until I happened to notice and
point out to them - that the compiler they were using was, in fact a C++
compiler.
 
K

Kaz Kylheku

I'm quite familiar with an organization that used C/C++ for many years,
for all its mission critical work, without knowing which compiler (i.e.,
which language) they were using. So, it was very important to them to
write code that would compile (and compile correctly - i.e., the
resulting executable produce the right results) under either language.

This is because they were writing C, but compiling (unknowingly) with C++.

Strange.

Did nobody ever notice during debugging that object files contained mangled
names? (Or was a toolchain used with a more advanced linker that doesn't have
to mangle names?)

Nobody ever used ``new'', ``class'', or any other C++ keyword, as a name and
wonder why the compiler was rejecting a perfectly good C identifier?

How about linkage; didn't anyhone ever notice what libraries are being
linked to the code? Did their toolchain not have a separate C++ library
for C++ programs?
 
N

Nobody

Interesting that it has *no* values, since it could hold one
without requiring any space.

Indeed.

Most functional languages have a "unit" type with exactly one value.
Unlike C's "void", it's an actual value (although in a statically-typed
language, any references to it are likely to be optimised away).
 
K

Keith Thompson

Kaz Kylheku said:
So that leaves ``while''. What is that?

If you have no name for the role that the keyword ``while'' plays in
the while statement, you have no basis for objecting to my calling
it an operator.
[...]

The standard consistently uses the term "operator" for things that can
appear in expressions. The definition of "expression" is:

An expression is a sequence of operators and operands that
specifies computation of a value, or that designates an object
or a function, or that generates side effects, or that performs
a combination thereof.

(quoting from n869 just this once), but I don't think it's changed).

I've quibbled about this definition before, but it seems clear enough
that operators occur only in expression, which ``while'' cannot.
 
K

Keith Thompson

Ioannis Vranos said:
Just for information, C95 also provides keywords for unary and binary
operators with <iso646.h>.

C99 does the same thing, of course (I had forgotten about that).

Except that they're macros, not keywords, but it's the same idea.
So for example you can write:


#include <iso646.h>



int main(void)
{
int x=5, y= 4, a=0;

/* ... */


if(x> 1 and y< 2)
/* Do something. */

else
if(x> 10 or y> 10)
/* Do something else. */


if(not a)
/* Do something. */


return 0;
}

Or you can just write:

#include <iso646.h>
int main(void)
{
int x=5, y= 4, a=0;
/* ... */
if(x> 1 and y< 2)
/* Do something. */
else
if(x> 10 or y> 10)
/* Do something else. */
if(not a)
/* Do something. */
return 0;
}

None of the vertical whitespace in your code was necessary or helpful
in reading the code. (*Three* blank lines between #include <iso606.h>
and int main(void)? Why??)
 
K

Keith Thompson

As of the last committee meeting, it now has "alignof", too.

I like it.

Is there also a mechanism (say, a new macro in <limits.h>) to query
the maximum alignment for any type, so mere mortals can write
malloc()-like functions?
 
F

frank

That actually sounds useful, sorta.

I'm gonna guess. I'm a on a hot streak with recreating intrinsics,
having this week coded something close to fortran's spacing(x), which
tells you how far you've got to go before you hit the next floating point
value.

Does alignof() replicate the function that union ALIGN does in chp 8 of
Unleashed?
 
K

Keith Thompson

Joe Wright said:
Eric said:
Joe said:
Richard wrote:
[ snip ]

For sure. But I don't see how that has any impact on the fact that for
years voids have been used for holding "unsuitable" things. Joe Wright's
incredulous demand for a "citation" had me in stitches.

I'm OK providing entertainment. Can you provide an instance of a
voids holding anything at all?

There is no void type. There is however a void* type. I don't find
where a function pointer can be assigned to a variable of type
void*. Do you?

There *is* a void type, saith 6.2.5p19:

The void type comprises an empty set of values; it is
an incomplete type that cannot be completed.
I know that. So it can't hold anything.
Since there are no values of type void, however, it is not
possible to have a void variable that holds one.

There is no guarantee that a function pointer can be converted
to or from a void* (or any other data pointer) "meaningfully."
That is, the converted pointer need not be usable, and converting
it back to the original type need not produce the original value
undamaged.
I know that too. Why are you telling me this instead of Richard?

Probably because you claimed that "There is no void type", and you
were mistaken. (I won't comment on what Richard wrote, since I've
only seen the one quoted paragraph.)
 

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
474,008
Messages
2,570,268
Members
46,867
Latest member
Lonny Petersen

Latest Threads

Top