Common misconceptions about C (C95)

E

Eric Sosman

Kaz said:
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.

Right. And `while' is called a "keyword." There is no
good reason to slap a more specific term on it, particularly
not the term "operator," which the Standard only to the members
of an explicit list of things not including `while'.

Some punctuators denote operators (in suitable contexts).
One keyword also denotes an operator. It does not follow that
"operator" can be applied indiscriminately to all keywords or
all punctuators or all lexical elements of whatever stripe.
 
B

Ben Bacarisse

Joe Wright said:
Fascinating.

#include <stdio.h>
int main(void) {
printf("%d\n", (int)sizeof (void));

sizeof (void) is a constraint violation and so a diagnostic is
required.
return 0;
}

DJGPP and MinGW (gcc) quietly prints 1.

gcc does not compile C by default. If you ask it to, does it not
issue a diagnostic as required?
cl (Microsoft C) warns that 'sizeof returns 0' but compiles and prints 0.
Pelles C says it's an error and refuses to compile it.

Microsoft gets it right. I just saw a flying pig.

Indeed it does because all that is required is a diagnostic and
"sizeof returns 0" counts as one. I prefer the behaviour you report
from Pelles. It is closer to the spirit of the language standard.
 
K

Keith Thompson

(e-mail address removed) (Richard Harter) writes:
[...]
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.

That sounds rather odd. You have a choice of two idioms, (a)
enclose the operand in parentheses or (b) omit the parentheses.
Idiom (a) is more robust. You insist on using idiom (b) to the
point of changing existing working code elsewhere rather than
using the more robust idiom (a). This doesn't sound like good
practice to me.

Here's my standard example of preprocessor abuse:

#include <stdio.h>

#define SIX 1+5
#define NINE 8+1

int main(void)
{
printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
return 0;
}

This is obviously silly, but you can imagine a more realistic example.

Suppose the macros SIX and NINE (assume better names) are provided by
some header that I didn't write. Should I write

printf("%d * %d = %d\n", (SIX), (NINE), (SIX) * (NINE));

to allow for the possibility that the library's author is either
incompetent or malicious? Is there any more reason to do so
if the operator is "sizeof" rather than "*"?

If you write a macro that's intended to be used in an expression
context, it's your responsibility to provide parentheses as needed,
so the user doesn't need to worry about it. (For the standard
headers, this is explicitly required.)
 
K

Keith Thompson

Joe Wright said:
Fascinating.

#include <stdio.h>
int main(void) {
printf("%d\n", (int)sizeof (void));
return 0;
}

DJGPP and MinGW (gcc) quietly prints 1.
cl (Microsoft C) warns that 'sizeof returns 0' but compiles and prints 0.
Pelles C says it's an error and refuses to compile it.

Microsoft gets it right. I just saw a flying pig.

No, Microsoft gets it wrong; only Pelles C gets it right.

More precisely, both gcc and Microsoft C invent a meaning for sizeof
(void) *as an extension*.

gcc permits pointer arithmetic on void* values; adding N to a void*
value advances the address by N bytes. It does this by pretending
that sizeof (void) == 1. With options to make it conform to a C
standard, specficially "-pedantic", gcc issues a warning.

In fact, both "gcc -pedantic" and Microsoft C are conforming with
respect to this case; ``sizeof (void)'' is a constraint violation,
and both issue a diagnostic. The fact that it's a warning rather
than a fatal error is irrelevant as far as conformance is concerned,
as is the fact that Microsoft C's warning includes the silly claim
that "sizeof returns 0". (Perhaps MS C behaves more sensibly with
the right options.)
 
E

Eric Sosman

Joe said:
Fascinating.

#include <stdio.h>
int main(void) {
printf("%d\n", (int)sizeof (void));
return 0;
}

DJGPP and MinGW (gcc) quietly prints 1.

In its default mode of operation, gcc does not conform to
the C Standard (any version). You can make it more law-abiding
by adding various command-line option flags, some of which will
disable this particular gcc extension.
cl (Microsoft C) warns that 'sizeof returns 0' but compiles and prints 0.
Pelles C says it's an error and refuses to compile it.

Microsoft gets it right. I just saw a flying pig.

After issuing the required diagnostic, the implementation
can reject or accept the source. In the latter case, of course,
there is no "right" or "wrong" any more, since the code has
already transgressed (or transcended) the developer/implementor
contract spelled out by the Standard.
 
E

Eric Sosman

Keith said:
Joe Wright said:
[...]
Microsoft gets it right. I just saw a flying pig.

No, Microsoft gets it wrong; only Pelles C gets it right.
[...]
In fact, both "gcc -pedantic" and Microsoft C are conforming with
respect to this case; ``sizeof (void)'' is a constraint violation,
and both issue a diagnostic. The fact that it's a warning rather
than a fatal error is irrelevant as far as conformance is concerned,
as is the fact that Microsoft C's warning includes the silly claim
that "sizeof returns 0". (Perhaps MS C behaves more sensibly with
the right options.)

Why do you describe conforming behavior as "wrong?"
 
K

Keith Thompson

Richard Heathfield said:
I must disagree. Since minutiae are measuriae of arc, and tangents are
straight lines, "tangential minutiae" is a contradiction in terms.
Therefore, one cannot seize on tangential minutiae.

Tangents needn't be straight lines; two circles can be tangent to each
other. Therefore tangential minutiae can exist. Whether one can
seize on them is another question. Whether one should is yet another.
 
K

Keith Thompson

Eric Sosman said:
Keith said:
Joe Wright said:
[...]
Microsoft gets it right. I just saw a flying pig.

No, Microsoft gets it wrong; only Pelles C gets it right.
[...]
In fact, both "gcc -pedantic" and Microsoft C are conforming with
respect to this case; ``sizeof (void)'' is a constraint violation,
and both issue a diagnostic. The fact that it's a warning rather
than a fatal error is irrelevant as far as conformance is concerned,
as is the fact that Microsoft C's warning includes the silly claim
that "sizeof returns 0". (Perhaps MS C behaves more sensibly with
the right options.)

Why do you describe conforming behavior as "wrong?"

Because I think it's wrong. Specifically, the message's claim that
"sizeof returns 0" may be correct for that implementation, but it's
incorrect as a general statement.

The standard permits a conforming implementation's diagnostics to be
wrong (i.e., factually incorrect). And since the standard doesn't
define the word "wrong", I feel free to use it with its common English
meaning. Whether it applies in this case is admittedly a matter of
opinion.

You also snipped the immediately following paragraph, which started
with "More precisely ...". I acknowledged that I was being imprecise
and went on to explain what I meant more precisely.
 
I

Ian Collins

Kaz said:
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?

With the exception of C++ specific libraries (the run-time for example),
why should it? Most platforms have conditional wrappers in their
headers and one set of libraries.
 
L

lawrence.jones

Keith Thompson said:
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?

There's a max_align_t typedef in <stddef.h>. See N1397 in the most
recent mailing for (most of) the details. There will be an updated
draft (N1425) in the next mailing, which should be out in a week or two.
 
L

lawrence.jones

Nick Keighley said:
doesn't offsetof() qualify as reflective? It needs compiler magic.

offsetof() is a macro, not an operator. It can be implemented using
normal operators with just a little cooperation from the compiler, it
doesn't require full-blown magic. :)
 
S

Seebs

No. And Thursdays aren't nearly as notorious as they used to be. :)

Oh, good.

Actually, I'm pretty happy about alignof(). I had gotten by with the
assumption that no type could have an alignment requirement stricter than
its size (because some_t foo[2]), but that's... Well, I wasn't super happy
with it.

-s
 
K

Keith Thompson

Phil Carmody said:
Yes, Gnus fails to flow the content correctly. File a bug!

No, Gnus got it right. With "format=flowed", flowed text is indicated
by trailing spaces; there were none in Joe's article (at least not by
the time it got to me). See RFC 3676.

(What I found odd was the combination of "charset=UTF-8" and "7bit".
Perhaps the newsreader would change it to "8bit" if the article
contained any non-7bit characters.)
 
K

Kaz Kylheku

Works for me.

Have you checked all of the normative references? Maybe ISO 2382-1 has
a definition for operator. I don't have this document.

The term ``local variable'' also cannot be found in the standard.

Good luck convincing the world to say ``object with automatic storage
duration''.

The standard does use the term ``local'' in several places without really
defining what it means. The term ``variable'' (as a noun) also appears in
normative text, but it is not defined.

First occurence: 6.8.5.3 The for statement.

``If clause-1 is a declaration, the scope of any variables it declares
is the remainder of the declaration and the entire loop, including the
other two expressions; it is reached in the order of execution before
the first evaluation of the controlling expression.''

Maybe it's found in ISO 2382-1.
 
R

Richard Tobin

Keith Thompson said:
(What I found odd was the combination of "charset=UTF-8" and "7bit".
Perhaps the newsreader would change it to "8bit" if the article
contained any non-7bit characters.)

Perhaps, or perhaps it's just wrong: the receiver doesn't have to do
anything in response to a 7bit transfer encoding (unlike base64 for
example), so it may well just ignore it.

-- Richard
 
K

Keith Thompson

Kaz Kylheku said:
Have you checked all of the normative references? Maybe ISO 2382-1 has
a definition for operator. I don't have this document.

The C standard does define the word "operator".

C99 6.4.6p2:

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 _operator_ (other forms
of operator also exist in some contexts). An _operand_ is an
entity on which an operator acts.

Underscores denote italics in the standard.

I suppose there's some wiggle room in the statement that "other
forms of operator also exist in some contexts", but the standard
*never* uses the word "operator" in a way that allows "return"
to be considered an operator. Probably it refers to the "sizeof"
and cast operators, which don't take the form of punctuators.
The term ``local variable'' also cannot be found in the standard.

Good luck convincing the world to say ``object with automatic storage
duration''.

I've found that people using the term "local variable" tend not to
make the distinction between scope and storage duration. C, along
with its descendants, is a bit unusual in making this distinction.

This isn't to suggest that people using the term "local variable"
don't understand the distinction; typically it doesn't matter in the
particular context being discussed.
The standard does use the term ``local'' in several places without really
defining what it means. The term ``variable'' (as a noun) also appears in
normative text, but it is not defined.

First occurence: 6.8.5.3 The for statement.

``If clause-1 is a declaration, the scope of any variables it declares
is the remainder of the declaration and the entire loop, including the
other two expressions; it is reached in the order of execution before
the first evaluation of the controlling expression.''

Maybe it's found in ISO 2382-1.

That doesn't turn out to be a good example. The text you quote
does appear in the C99 standard, but not in N1256. The change is
in TC3, changing "variables" to "identifiers", in response to DR
#292, <http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_292.htm>.
(The DR proposed the word "objects"; the committee response changed
it to "identifiers".)

Note that the committee did not make most of the suggested changes.
I haven't studied them all, but apparently they felt that the use
of the word "variable" is acceptable in non-normative text, such
as footnotes. (Not unreasonable, IMHO.)
 
E

Eric Sosman

Kaz said:
Have you checked all of the normative references? Maybe ISO 2382-1 has
a definition for operator. I don't have this document.

Have *you* found even one normative use of "operator" to
describe C's `while' keyword? Just one teeny-tiny use? One?
The term ``local variable'' also cannot be found in the standard.
[...]

Isn't there a difference between using a term not found
in the Standard, and using a Standard term in a way different
from the Standard's usage? Shall we discuss the `return'
function and the `void' qualifier and the `switch' type?
 

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

No members online now.

Forum statistics

Threads
474,007
Messages
2,570,266
Members
46,865
Latest member
AveryHamme

Latest Threads

Top