If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.
Sure, you may still want to write something like
a = b = c;
but Python has found a way to allow that, without saying that “b = c” has to return a value.
(let ((i 0)) (list (incf i) (incf i) (incf i)))(1 2 3)
while( (ch = fgetc(fp)) != EOF)
is the idiomatic way of accessing a stream a character by character in
C. So you would disallow this.
If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
If you want to make C a safer language, one obvious thing is to disallow
using “=” in the middle of an expression. Instead of returning the value >> of the expression, have it return void. Or just disallow it syntactically
altogether.
I think that C would have been a safer language if assignment had been a statement, not an expression
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
If you want to make C a safer language, one obvious thing is to disallow >>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>> altogether.
I think that C would have been a safer language if assignment had been a
statement, not an expression
Surely someone has studied this, no? There must be some paper
describing bugs "in the wild"* and categorising them by what language features would have made them either impossible or less likely. I don't
know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
* I mean to exclude bugs that get found early. For example, I've never
seen a = vs. == bug that survived even the most crude tests (and most,
like many other typo bugs, don't survive compilation without being
picked up).
On 09/02/2024 10:16, Ben Bacarisse wrote:
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:Surely someone has studied this, no? There must be some paper
If you want to make C a safer language, one obvious thing is to disallow >>>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>>> altogether.
I think that C would have been a safer language if assignment had been a >>> statement, not an expression
describing bugs "in the wild"* and categorising them by what language
features would have made them either impossible or less likely. I don't
know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
* I mean to exclude bugs that get found early. For example, I've never
seen a = vs. == bug that survived even the most crude tests (and most,
like many other typo bugs, don't survive compilation without being
picked up).
This is what ChatGPT says ...
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
If you want to make C a safer language, one obvious thing is to disallow >>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>> altogether.
I think that C would have been a safer language if assignment had been a
statement, not an expression
Surely someone has studied this, no? There must be some paper
describing bugs "in the wild"* and categorising them by what language features would have made them either impossible or less likely. I don't
know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
* I mean to exclude bugs that get found early. For example, I've never
seen a = vs. == bug that survived even the most crude tests (and most,
like many other typo bugs, don't survive compilation without being
picked up).
Richard Harnden <richard.nospam@gmail.invalid> writes:
On 09/02/2024 10:16, Ben Bacarisse wrote:
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:Surely someone has studied this, no? There must be some paper
If you want to make C a safer language, one obvious thing is to disallow >>>>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>>>> altogether.
I think that C would have been a safer language if assignment had been a >>>> statement, not an expression
describing bugs "in the wild"* and categorising them by what language
features would have made them either impossible or less likely. I don't >>> know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
* I mean to exclude bugs that get found early. For example, I've never
seen a = vs. == bug that survived even the most crude tests (and most,
like many other typo bugs, don't survive compilation without being
picked up).
This is what ChatGPT says ...
Seriously? You do know how large language models work, yes?
If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.
Sure, you may still want to write something like
a = b = c;
but Python has found a way to allow that, without saying that “b = c” has to return a value.
On 09/02/2024 00:39, Lawrence D'Oliveiro wrote:
If you want to make C a safer language, one obvious thing is to disallow
using “=” in the middle of an expression. Instead of returning the value >> of the expression, have it return void. Or just disallow it syntactically
altogether.
Sure, you may still want to write something like
a = b = c;
but Python has found a way to allow that, without saying that “b = c” has
to return a value.
I suspect that quite a number of existing programs will become invalid.
But what is the problem with 'a = b = c'?
The real problems with
assignments inside expressions is when you accidentally use '=' instead
of '=='. That's due to a poor choice of syntax.
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a, b, c all having different numerical types.
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
If you want to make C a safer language, one obvious thing is to disallow
using “=” in the middle of an expression. Instead of returning the value >> of the expression, have it return void. Or just disallow it syntactically
altogether.
I think that C would have been a safer language if assignment had been a statement, not an expression (such as is the case in Pascal, for
example). But I don't think it is remotely feasible to change this in C
- you are fifty years too late.
I suggest that the bug of using "=" where "==" was intended occurs
almost exclusively among inexperienced C programmers, particularly those
who are inexperienced with programming in general.
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "="
and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and =
for comparison, and when I switched back to C, I was always writing "="
for "==".
On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I suggest that the bug of using "=" where "==" was intended occurs
almost exclusively among inexperienced C programmers, particularly those
who are inexperienced with programming in general.
Almost exclusively. I've had this sneak upon me maybe once or twice in
the past 15 years. GCC warns well in most situations in which the typo
is made, so it doesn't easily sneak through.
This is in the bug category of "used to be menacing before we had better diagnostics", along with forgetting to include <stdlib.h> before using malloc.
On 09/02/2024 17:22, Malcolm McLean wrote:
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "="
and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and
= for comparison, and when I switched back to C, I was always writing
"=" for "==".
Fortran must have changed considerably since I last used it.
It was "=" to assign, and ".EQ." for equality.
I assume you mean another language. My normal one does use := and = like that, and switching to/from C gives problems: you write = in C instead
of ==, and in mine I'd write = instead of :=. However:
a = b
was a no-op in my language (or rather, it compared then discarded the result), leading to puzzling bugs. Now I usually detect such statements.
On 09/02/2024 17:38, Kaz Kylheku wrote:
On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
I suggest that the bug of using "=" where "==" was intended occurs
almost exclusively among inexperienced C programmers, particularly those >>> who are inexperienced with programming in general.
Almost exclusively. I've had this sneak upon me maybe once or twice in
the past 15 years. GCC warns well in most situations in which the typo
is made, so it doesn't easily sneak through.
This is in the bug category of "used to be menacing before we had better
diagnostics", along with forgetting to include <stdlib.h> before using
malloc.
How does gcc know whether 'if (a = b)' is meant to be an assignment or comparison?
Simply warning on the possibility is not going to be helpful, because
you will be swamped with output that may hide more important matters.
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:
If you want to make C a safer language, one obvious thing is to disallow >>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>> altogether.
I think that C would have been a safer language if assignment had been
a statement, not an expression (such as is the case in Pascal, for
example). But I don't think it is remotely feasible to change this in
C - you are fifty years too late.
The nearest you can come to changes like this in C would be optional
warnings or checks in compilers and static analysers.
I suggest that the bug of using "=" where "==" was intended occurs
almost exclusively among inexperienced C programmers, particularly those
who are inexperienced with programming in general.
It's a mistake that's made because the programmer assumes that "="
is a comparison operator, as it is in mathematics and in some other programming languages. It's an easy and understandable mistake
to make, but any reasonably experienced C programmer will have
internalized the fact that "=" means assignment, not comparison.
To a newbie, `if (x = y)` *looks like* a comparison. To an
experienced C programmer it doesn't.
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "="
and "==" occasionally.)
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come up, because ":=" doesn't look like a comparison even to a newbie. But it's
far too late to fix that in any language called "C".
bart wrote:
On 09/02/2024 17:22, Malcolm McLean wrote:
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "=" >>>> and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and
= for comparison, and when I switched back to C, I was always writing
"=" for "==".
Fortran must have changed considerably since I last used it.
It was "=" to assign, and ".EQ." for equality.
I assume you mean another language. My normal one does use := and = like
that, and switching to/from C gives problems: you write = in C instead
of ==, and in mine I'd write = instead of :=. However:
a = b
was a no-op in my language (or rather, it compared then discarded the
result), leading to puzzling bugs. Now I usually detect such statements.
as some maybe know im from time to time write my compiler on c based
langage and also i hardly think how to simplify and expand syntax and construction
as to this problem how ewentually replace = and == at present time i
just found this problem unresolvable :c
what i think = coud eventually stay though it also could have
alternative.. == is in turn clearly wrong but one would need unicode
sign for this i guess.. there is need for some sign like = with a small
"?" above it
≟ possibly
a≟b
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come up,
because ":=" doesn't look like a comparison even to a newbie. But it's
far too late to fix that in any language called "C".
If I were designing a new language, I'd consider using ":=" for
assignment, "==" for equality, and not using "=" for anything.
In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
means assignment, and "==" either doesn't exist or means equality. I'd
avoid "=" because it's ambiguous across languages (and that's almost
entirely C's fault, inherited from B).
Historically, C's predecessor B used "=" for assignment and "==" for equality, while B's predecessor BCPL used ":=" for assignment and "="
for equality.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come up,
because ":=" doesn't look like a comparison even to a newbie. But it's
far too late to fix that in any language called "C".
If I were designing a new language, I'd consider using ":=" for
assignment, "==" for equality, and not using "=" for anything.
In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
means assignment, and "==" either doesn't exist or means equality. I'd
avoid "=" because it's ambiguous across languages (and that's almost
entirely C's fault, inherited from B).
There are too many situations where assignment being an expression is a useful facet of the language; i am not willing to sacrifice that for an ill-defined ideal of “safety”.
On 09/02/2024 11:16, Ben Bacarisse wrote:
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:Surely someone has studied this, no? There must be some paper
If you want to make C a safer language, one obvious thing is to disallow >>>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>>> altogether.
I think that C would have been a safer language if assignment had been a >>> statement, not an expression
describing bugs "in the wild"* and categorising them by what language
features would have made them either impossible or less likely. I don't
know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
I think it is very difficult to get good statistics on this kind of thing. You can't really do a controlled study comparing one group programming in
"C where assignment is an expression" with a group programming in "C where assignment is a statement". And you certainly can't do a double-blind placebo controlled test!
On 09/02/2024 13:17, Ben Bacarisse wrote:
Richard Harnden <richard.nospam@gmail.invalid> writes:
On 09/02/2024 10:16, Ben Bacarisse wrote:Seriously? You do know how large language models work, yes?
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:Surely someone has studied this, no? There must be some paper
If you want to make C a safer language, one obvious thing is to disallow >>>>>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically
altogether.
I think that C would have been a safer language if assignment had been a >>>>> statement, not an expression
describing bugs "in the wild"* and categorising them by what language
features would have made them either impossible or less likely. I don't >>>> know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
* I mean to exclude bugs that get found early. For example, I've never >>>> seen a = vs. == bug that survived even the most crude tests (and most, >>>> like many other typo bugs, don't survive compilation without being
picked up).
This is what ChatGPT says ...
Sure: It has read the entire internet - especially the the bit about how Rust is better than C, apparently - and regurgitates the same.
Considering my five seconds of effort; I didn't think it was /that/ bad of
a list.
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall not be used in expressions that yield a boolean value”.
But it's far too late to fix that in any language called "C".
On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:
There are too many situations where assignment being an expression is a
useful facet of the language; i am not willing to sacrifice that for an
ill-defined ideal of “safety”.
If you consider it “ill-defined”, consider the number of people who have developed the habit of writing
if (NULL == p) ...
instead of the more natural
if (p == NULL) ...
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall not be used in expressions that yield a boolean value”.
On 09/02/2024 22:41, Ben Bacarisse wrote:...
Yes, it's a good summary of what passes for "common knowledge". But II did have an example recently in my own code recently (shipped,
was talking about something else altogether -- actual bugs found in real
code, maybe taken from an analysis of security advisories. How many can
(to take one example) be attributed, in whole or in part, for using
assignment in a larger expression?
commercial, tested, supposedly bug free code). There was an assignment in a if expression which somehow slipped through. But it's only one
example.
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 11:16, Ben Bacarisse wrote:
David Brown <david.brown@hesbynett.no> writes:
On 09/02/2024 01:39, Lawrence D'Oliveiro wrote:Surely someone has studied this, no? There must be some paper
If you want to make C a safer language, one obvious thing is to disallow >>>>> using “=” in the middle of an expression. Instead of returning the value
of the expression, have it return void. Or just disallow it syntactically >>>>> altogether.
I think that C would have been a safer language if assignment had been a >>>> statement, not an expression
describing bugs "in the wild"* and categorising them by what language
features would have made them either impossible or less likely. I don't >>> know of any (it was not even remotely my field) but there is such a
large pool of data out there I can't imagine that it's not been done.
I think it is very difficult to get good statistics on this kind of thing. >> You can't really do a controlled study comparing one group programming in
"C where assignment is an expression" with a group programming in "C where >> assignment is a statement". And you certainly can't do a double-blind
placebo controlled test!
True. But there are literally thousands of significant bugs logged
every day in key systems components. A retrospective analysis of these would, I think, be very interesting.
On 2024-02-10, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall >> not be used in expressions that yield a boolean value”.
I skimmed through MISRA some years ago and wasn't very impressed by it, actually.
It's full the kind of coding rules that you might want to enforce
if you have to produce a bunch of C, and the only people you are given
are ones who shouldn't even remotely be doing such a thing.
We might call those coders Les MISRAbles. :)
The rules are not suitable for people who know what they are doing
(and use tools effectively) and detrimental to the code.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall >> not be used in expressions that yield a boolean value”.
Oddly worded. They can't mean what they say.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall >>> not be used in expressions that yield a boolean value”.
I presume they mean expressions used as conditions, but unless they
define what they the phrase "boolean value" somwhere, that's not what
they wrote.
Editing error.
I presume they mean expressions used as conditions, but unless they
define what they *mean by* the phrase "boolean value" somwhere, that's
not what they wrote.
Lawrence D'Oliveiro wrote:
On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:
There are too many situations where assignment being an expression is a
useful facet of the language; i am not willing to sacrifice that for an
ill-defined ideal of “safety”.
If you consider it “ill-defined”, consider the number of people who have >> developed the habit of writing
if (NULL == p) ...
instead of the more natural
if (p == NULL) ...
Y'know, there's some coding style guide that explicitly states _not_ to do those kinds of “yoda comparisons”, but i've never seen any code that actually uses them.
On Fri, 9 Feb 2024 00:53:42 +0000, Malcolm McLean wrote:
while( (ch = fgetc(fp)) != EOF)
is the idiomatic way of accessing a stream a character by character in
C. So you would disallow this.
Yes!
All in all, this means MISRA can be useful and appropriate in some
cases, and inappropriate in other cases - they are certainly not
something you'd use for all C programming.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
I had a look at the MISRA specs, and they say “assignment operators
shall not be used in expressions that yield a boolean value”.
Oddly worded. They can't mean what they say.
In MISRA C 2012, the assignment rule is simpler : "The result of an assignment operator should not be used".
On Sat, 10 Feb 2024 13:06:13 +0000, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
I had a look at the MISRA specs, and they say “assignment operators
shall not be used in expressions that yield a boolean value”.
Oddly worded. They can't mean what they say.
It is cleverly worded. The idea is obviously to allow chained assignments, while disallowing doing a test on the value being assigned. The examples
make this clear.
On 10/02/2024 14:06, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:Oddly worded. They can't mean what they say.
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall >>> not be used in expressions that yield a boolean value”.
It says "Assignment operators shall not be used in expressions which return Boolean values", at least in my copy of MISRA 1998. Of course, the use of "return" just makes it worse.
They explain with examples:
"""
For example write:
x = y;
if ( x != 0 )
{
foo();
}
and not:
if ( ( x = y ) != 0 )
{
foo();
}
or even worse:
if ( x = y )
{
foo();
}
This helps to avoid getting ‘=’and ‘==’confused, and assists the static
detection of mistakes.
"""
David Brown <david.brown@hesbynett.no> writes:
On 10/02/2024 14:06, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:Oddly worded. They can't mean what they say.
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall
not be used in expressions that yield a boolean value”.
It says "Assignment operators shall not be used in expressions which return >> Boolean values", at least in my copy of MISRA 1998. Of course, the use of >> "return" just makes it worse.
They explain with examples:
"""
For example write:
x = y;
if ( x != 0 )
{
foo();
}
and not:
if ( ( x = y ) != 0 )
x = y is an expression that yields a value of the type of x (after
lvalue conversion). This is unlikely to be _Bool which (even if they
mean _Bool instead of Boolean) is why I say they can't mean what they
say.
Your later post in reply to someone else explains that they don't mean
what they say though, even a few minutes after reading it, I can't
remember what the clarification was.
{
foo();
}
or even worse:
if ( x = y )
{
foo();
}
This helps to avoid getting ‘=’and ‘==’confused, and assists the static
detection of mistakes.
"""
These sorts of guides often use silly examples like this. What is the
MIRSA preferred why to write
while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
... use x ...
}
? Presumably they want people to duplicate the call:
x = get_the_next_x(...);
while (x != NO_MORE_Xs) {
... use x ...
x - get_the_next_y(...);
}
or maybe use break:
while (1) {
x = get_the_next_x(...);
if (x != NO_MORE_Xs) break;
... use x ...
}
Neither looks good to me.
David Brown <david.brown@hesbynett.no> writes:
On 10/02/2024 14:06, Ben Bacarisse wrote:
This helps to avoid getting ‘=’and ‘==’confused, and assists the static
detection of mistakes.
"""
These sorts of guides often use silly examples like this. What is the
MIRSA preferred why to write
while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
... use x ...
}
? Presumably they want people to duplicate the call:
x = get_the_next_x(...);
while (x != NO_MORE_Xs) {
... use x ...
x - get_the_next_y(...);
}
or maybe use break:
while (1) {
x = get_the_next_x(...);
if (x != NO_MORE_Xs) break;
... use x ...
}
Neither looks good to me.
It says "Assignment operators shall not be used in expressions which
return Boolean values", at least in my copy of MISRA 1998.
or maybe use break:
while (1) {
x = get_the_next_x(...);
if (x != NO_MORE_Xs) break;
... use x ...
}
On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:
It says "Assignment operators shall not be used in expressions which
return Boolean values", at least in my copy of MISRA 1998.
One thing with that wording, it would disallow chained assignments in such innocuous cases as
a = b = c == d;
since, after all, the expression is returning a boolean.
But this point is moot, since the later revision disallows assignment chaining completely, anyway.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:
It says "Assignment operators shall not be used in expressions which
return Boolean values", at least in my copy of MISRA 1998.
One thing with that wording, it would disallow chained assignments in
such innocuous cases as
a = b = c == d;
since, after all, the expression is returning a boolean.
The type of c == d is int, but the value will be either 0 or 1.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:
It says "Assignment operators shall not be used in expressions which >>>>> return Boolean values", at least in my copy of MISRA 1998.
One thing with that wording, it would disallow chained assignments in
such innocuous cases as
a = b = c == d;
since, after all, the expression is returning a boolean.
The type of c == d is int, but the value will be either 0 or 1.
That is the only kind of “boolean” C has.
No it isn't. C99 added _Bool, which can be called bool if you include <stdbool.h>. C23 (not yet released) will make bool a keyword, with
_Bool as an alternative spelling.
But the equality and relational operators still yield results of type
int with value 0 or 1.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:[...]
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
The type of c == d is int, but the value will be either 0 or 1.
That is the only kind of “boolean” C has.
No it isn't. C99 added _Bool, which can be called bool if you include
<stdbool.h>. C23 (not yet released) will make bool a keyword, with
_Bool as an alternative spelling.
All just new, different names for what I said: still the only kind of
“boolean” C has.
I can imagine that you're trying to express something that's correct,
but I honestly have no idea what it might be.
C has a boolean type, called "_Bool" or "bool", added in C99. _Bool is
a distinct type, not the same as or compatible with any other type.
But the equality and relational operators still yield results of type
int with value 0 or 1.
On 09/02/2024 17:22, Malcolm McLean wrote:
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "="
and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and
= for comparison, and when I switched back to C, I was always writing
"=" for "==".
Fortran must have changed considerably since I last used it.
It was "=" to assign, and ".EQ." for equality.
I assume you mean another language. My normal one does use := and = like that, and switching to/from C gives problems: you write = in C instead
of ==, and in mine I'd write = instead of :=. However:
a = b
was a no-op in my language (or rather, it compared then discarded the result), leading to puzzling bugs. Now I usually detect such statements.
bart wrote:
On 09/02/2024 17:22, Malcolm McLean wrote:
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "=" >>>> and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and
= for comparison, and when I switched back to C, I was always writing
"=" for "==".
Fortran must have changed considerably since I last used it.
It was "=" to assign, and ".EQ." for equality.
I assume you mean another language. My normal one does use := and = like
that, and switching to/from C gives problems: you write = in C instead
of ==, and in mine I'd write = instead of :=. However:
a = b
was a no-op in my language (or rather, it compared then discarded the
result), leading to puzzling bugs. Now I usually detect such statements.
it seem clear by me that if someone want upbild c-liek language
(and many people want including me) unicode is needed...
as i previously said yopu need one sign for == and one sign for = (or :=)
this conclusion comes from my study of what is needed and what
could be replaced...this basic set of operators/signs in ansi is to
natrrow and yet those wighs come from outside computer world
imo such operation as assigment is kinda computer specific and = dont
wuite fits
watching the unicode signs and tryin slightly (initially, spending few minutes on it as for now)
https://en.wikipedia.org/wiki/List_of_Unicode_characters
i didnt find what would fit and what fits best
temporarely i put empty square as example
x▭100, y▭200, z▭x+y
definitelly assuming that i need to drop ansi and find in unicode is
some kind of decision (step up)
fir wrote:
bart wrote:in fact i also think that more then one sign for asigments is needed
On 09/02/2024 17:22, Malcolm McLean wrote:
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "=" >>>>> and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and >>>> = for comparison, and when I switched back to C, I was always writing
"=" for "==".
Fortran must have changed considerably since I last used it.
It was "=" to assign, and ".EQ." for equality.
I assume you mean another language. My normal one does use := and = like >>> that, and switching to/from C gives problems: you write = in C instead
of ==, and in mine I'd write = instead of :=. However:
a = b
was a no-op in my language (or rather, it compared then discarded the
result), leading to puzzling bugs. Now I usually detect such statements.
it seem clear by me that if someone want upbild c-liek language
(and many people want including me) unicode is needed...
as i previously said yopu need one sign for == and one sign for = (or :=)
this conclusion comes from my study of what is needed and what
could be replaced...this basic set of operators/signs in ansi is to
natrrow and yet those wighs come from outside computer world
imo such operation as assigment is kinda computer specific and = dont
wuite fits
watching the unicode signs and tryin slightly (initially, spending few
minutes on it as for now)
https://en.wikipedia.org/wiki/List_of_Unicode_characters
i didnt find what would fit and what fits best
temporarely i put empty square as example
x▭100, y▭200, z▭x+y
definitelly assuming that i need to drop ansi and find in unicode is
some kind of decision (step up)
for example this x = foo(y) is something other than this x = y
and it is specially seen when using things liek
x y = foo(a,b,c)
becouse if i want to drep thsi gothic decorators as i name them you got
x y foo a b c
and you could want to denote optionally what is variables ina and
what is variables out and if so the = would look like
x= y= foo <-a <-b <-c thus output of the function probably should be
noted by differnt sign then assigment as it would increase readibility
x' y' foo "a "b "c
i dont knov hovever what signs it should be and there should be find a
way what can be optional
fir wrote:
bart wrote:in fact i also think that more then one sign for asigments is needed
On 09/02/2024 17:22, Malcolm McLean wrote:
On 09/02/2024 17:09, Keith Thompson wrote:
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "=" >>>>> and "==" occasionally.)
I had do to my PhD in Fortran, for my sins. It's := for assignment and >>>> = for comparison, and when I switched back to C, I was always writing
"=" for "==".
Fortran must have changed considerably since I last used it.
It was "=" to assign, and ".EQ." for equality.
I assume you mean another language. My normal one does use := and = like >>> that, and switching to/from C gives problems: you write = in C instead
of ==, and in mine I'd write = instead of :=. However:
a = b
was a no-op in my language (or rather, it compared then discarded the
result), leading to puzzling bugs. Now I usually detect such statements.
it seem clear by me that if someone want upbild c-liek language
(and many people want including me) unicode is needed...
as i previously said yopu need one sign for == and one sign for = (or :=)
this conclusion comes from my study of what is needed and what
could be replaced...this basic set of operators/signs in ansi is to
natrrow and yet those wighs come from outside computer world
imo such operation as assigment is kinda computer specific and = dont
wuite fits
watching the unicode signs and tryin slightly (initially, spending few
minutes on it as for now)
https://en.wikipedia.org/wiki/List_of_Unicode_characters
i didnt find what would fit and what fits best
temporarely i put empty square as example
x▭100, y▭200, z▭x+y
definitelly assuming that i need to drop ansi and find in unicode is
some kind of decision (step up)
for example this x = foo(y) is something other than this x = y
and it is specially seen when using things liek
x y = foo(a,b,c)
becouse if i want to drep thsi gothic decorators as i name them you got
x y foo a b c
and you could want to denote optionally what is variables ina and
what is variables out and if so the = would look like
x= y= foo <-a <-b <-c thus output of the function probably should be
noted by differnt sign then assigment as it would increase readibility
x' y' foo "a "b "c
i dont knov hovever what signs it should be and there should be find a
way what can be optional
On Sat, 10 Feb 2024 16:53:39 +0100, David Brown wrote:
In MISRA C 2012, the assignment rule is simpler : "The result of an
assignment operator should not be used".
Interesting. So no more chained assignments?
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:
It says "Assignment operators shall not be used in expressions which
return Boolean values", at least in my copy of MISRA 1998.
One thing with that wording, it would disallow chained assignments in such >> innocuous cases as
a = b = c == d;
since, after all, the expression is returning a boolean.
The type of c == d is int, but the value will be either 0 or 1. Is that
what you mean by an expression "returning a boolean" -- an expression of
type in with either 0 or 1 as the value?
On 10/02/2024 22:45, Ben Bacarisse wrote:
David Brown <david.brown@hesbynett.no> writes:
On 10/02/2024 14:06, Ben Bacarisse wrote:
This helps to avoid getting ‘=’and ‘==’confused, and assists the static
detection of mistakes.
"""
These sorts of guides often use silly examples like this. What is the
MIRSA preferred why to write
while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
... use x ...
}
? Presumably they want people to duplicate the call:
x = get_the_next_x(...);
while (x != NO_MORE_Xs) {
... use x ...
x - get_the_next_y(...);
}
or maybe use break:
while (1) {
x = get_the_next_x(...);
if (x != NO_MORE_Xs) break;
... use x ...
}
Neither looks good to me.
Another way is the use the gnu extension to put two statements inside
the condition, although when I tried it now it didn't like it:
while ({x = get_the_next_x(...); x != NO_MORE_Xs;}) {...}
I doubt that would cut any ice with MISRA. You're not technically using
the result of an assignment in an expression, but you're instead putting entire statements in there!
David Brown <david.brown@hesbynett.no> writes:
On 10/02/2024 14:06, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 09 Feb 2024 09:09:41 -0800, Keith Thompson wrote:Oddly worded. They can't mean what they say.
But it's far too late to fix that in any language called "C".
I had a look at the MISRA specs, and they say “assignment operators shall
not be used in expressions that yield a boolean value”.
It says "Assignment operators shall not be used in expressions which return >> Boolean values", at least in my copy of MISRA 1998. Of course, the use of >> "return" just makes it worse.
They explain with examples:
"""
For example write:
x = y;
if ( x != 0 )
{
foo();
}
and not:
if ( ( x = y ) != 0 )
x = y is an expression that yields a value of the type of x (after
lvalue conversion). This is unlikely to be _Bool which (even if they
mean _Bool instead of Boolean) is why I say they can't mean what they
say.
Your later post in reply to someone else explains that they don't mean
what they say though, even a few minutes after reading it, I can't
remember what the clarification was.
{
foo();
}
or even worse:
if ( x = y )
{
foo();
}
This helps to avoid getting ‘=’and ‘==’confused, and assists the static
detection of mistakes.
"""
These sorts of guides often use silly examples like this.
What is the
MIRSA preferred why to write
while ((x = get_the_next_x(...)) != NO_MORE_Xs) {
... use x ...
}
? Presumably they want people to duplicate the call:
x = get_the_next_x(...);
while (x != NO_MORE_Xs) {
... use x ...
x - get_the_next_y(...);
}
or maybe use break:
while (1) {
x = get_the_next_x(...);
if (x != NO_MORE_Xs) break;
... use x ...
}
Neither looks good to me.
On Sat, 10 Feb 2024 13:06:13 +0000, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
I had a look at the MISRA specs, and they say “assignment operators
shall not be used in expressions that yield a boolean value”.
Oddly worded. They can't mean what they say.
It is cleverly worded. The idea is obviously to allow chained assignments, while disallowing doing a test on the value being assigned. The examples
make this clear.
On 11/02/2024 02:00, Keith Thompson wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:Other lanaguages were designed with a "boolean" type which had special
On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:[...]
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
The type of c == d is int, but the value will be either 0 or 1.
That is the only kind of “boolean” C has.
No it isn't. C99 added _Bool, which can be called bool if you include >>>> <stdbool.h>. C23 (not yet released) will make bool a keyword, with
_Bool as an alternative spelling.
But the equality and relational operators still yield results of type
int with value 0 or 1.
All just new, different names for what I said: still the only kind of
“boolean” C has.
I can imagine that you're trying to express something that's correct,
but I honestly have no idea what it might be.
C has a boolean type, called "_Bool" or "bool", added in C99. _Bool is
a distinct type, not the same as or compatible with any other type.
Equality and relational operators yield results of type int, not _Bool.
An expression of any scalar type (which includes integer,
floating-point, and pointer types) can be used as a condition.
Assuming you agree with all that, I have no idea what you mean by "the
only kind of “boolean” C has".
rules (bool + bool would either be disallowed or yield 1
if both were true), and was intended to be used wherever a value was logically either true or false. C didn't and used a int with just
happened to be 1 or 0 for this purpose, and whilst booleans have now
been added, the old system cannot be entirely eliminated and remains.
You can achieve most of the benefits of a boolean type by aliasing "int'
to "bool" and defining "true" and "false", and a lot of C installations
do exactly this.
If you want to make C a safer language, one obvious thing is to disallow using “=” in the middle of an expression. Instead of returning the value of the expression, have it return void. Or just disallow it syntactically altogether.
The approach I am doing in cake (https://github.com/thradams/cake) is
require "bool" in conditional expression.
if (expression) ...
expression must be bool type.
BUT...
In C, a == b are of type int.
One type represents the type used by the language (int in this case) the second type is something like "working as bool" .
So the expression a == b has the "type int" working as "bool"
The other situation where two types are used are enumerators
enum E {A }
In C A is "int" but the second type is "working as enum E".
This allows me to check usage of different enumerators.
You are attributing a level of sophistication and forethought to the
MISRA authors that they simply did not have.
_Bool is a distinct type. Equality and relational operators yield
results of type int, which is not type _Bool.
Use type "bool" when you want a boolean. It is /not/ the same as an
int ...
int main(void) {
_Bool b;
int i;
_Bool *ptr = &i;
// constraint violation because _Bool and int are not compatible
}
Do you understand that int and _Bool are distinct and incompatible
types ...
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:
_Bool is a distinct type. Equality and relational operators yield
results of type int, which is not type _Bool.
There is no place where one type can be used, but the other cannot.
Incorrect.
int main(void) {
_Bool b;
int i;
_Bool *ptr = &i;
// constraint violation because _Bool and int are not compatible
}
Do you understand that int and _Bool are distinct and incompatible
types, and that neither is a "subtype" of the other?
Oh, and conversion from any scalar type to _Bool yields either (_Bool)0
or (_Bool)1, a major difference between _Bool and all other scalar
types.
On 12/02/2024 04:34, Keith Thompson wrote:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:
_Bool is a distinct type. Equality and relational operators yield
results of type int, which is not type _Bool.
There is no place where one type can be used, but the other cannot.
Incorrect.
int main(void) {
_Bool b;
int i;
_Bool *ptr = &i;
// constraint violation because _Bool and int are not compatible >>> }
Do you understand that int and _Bool are distinct and incompatible
types, and that neither is a "subtype" of the other?
Oh, and conversion from any scalar type to _Bool yields either (_Bool)0
or (_Bool)1, a major difference between _Bool and all other scalar
types.
Absolutely. There is a /massive/ difference between:
int * p;
_Bool b = p;
and
int x = p;
On Sun, 11 Feb 2024 19:12:35 -0800, Keith Thompson wrote:
int main(void) {
_Bool b;
int i;
_Bool *ptr = &i;
// constraint violation because _Bool and int are not compatible
}
Do you understand that int and _Bool are distinct and incompatible
types ...
No more so than, say, int and short int.
On 11/02/2024 17:05, David Brown wrote:
On 11/02/2024 17:55, Malcolm McLean wrote:So in fact it should be pretty obvious what LDO is getting at.
On 11/02/2024 02:00, Keith Thompson wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:Other lanaguages were designed with a "boolean" type which had
On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:[...]
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
The type of c == d is int, but the value will be either 0 or 1. >>>>>>>That is the only kind of “boolean” C has.
No it isn't. C99 added _Bool, which can be called bool if you
include
<stdbool.h>. C23 (not yet released) will make bool a keyword, with >>>>>> _Bool as an alternative spelling.
But the equality and relational operators still yield results of type >>>>>> int with value 0 or 1.
All just new, different names for what I said: still the only kind of >>>>> “boolean” C has.
I can imagine that you're trying to express something that's correct,
but I honestly have no idea what it might be.
C has a boolean type, called "_Bool" or "bool", added in C99. _Bool is >>>> a distinct type, not the same as or compatible with any other type.
Equality and relational operators yield results of type int, not _Bool. >>>>
An expression of any scalar type (which includes integer,
floating-point, and pointer types) can be used as a condition.
Assuming you agree with all that, I have no idea what you mean by "the >>>> only kind of “boolean” C has".
special rules (bool + bool would either be disallowed or yield 1
if both were true), and was intended to be used wherever a value
was logically either true or false. C didn't and used a int with just
happened to be 1 or 0 for this purpose, and whilst booleans have now
been added, the old system cannot be entirely eliminated and remains.
Yes, we all know that. (Well, everyone who has learned a bit of C99
knows that.) It's very difficult to change things in a language that
has as much use as C - changing the type of the value of expressions
like "x == y" would have been a breaking change. When C++ was forked
from C, it was able to make such breaking changes - thus "x == y"
gives a bool in C++. But for C, it was too late.
I used to say "bool breaks libraries" and this is exactly the problem.You can achieve most of the benefits of a boolean type by aliasing
"int' to "bool" and defining "true" and "false", and a lot of C
installations do exactly this.
No, you can't. That gives you the worst of all worlds.
Use type "bool" when you want a boolean. It is /not/ the same as an
int, or an enumerated type, or an unsigned char, or anything else that
might be used as a "home-made boolean" - it has important additional
characteristics. "Home-made boolean" types might be considered useful
in C90, but not in C99. Recommending them now is bad advice, and
recommending that you do so using the names "bool", "true" and "false"
which conflict with C's real boolean type is extraordinarily silly.
A
simple typedef bool "bool" to "int" and definiing "true" and "false"
creates problems because there are no namespaces, you export the
symbols, and either they clash or they create mismash of subtly
different Boolean types.
So I am not recommending it in user code.
However I am saying that it does achieve most of the benefits of having
a boolean type, and therefore people who do this are not entirely
stupid. But I'm talking about the C installation, so normally the person
who provides the compiler, not the user code.
On Sun, 11 Feb 2024 18:05:08 +0100, David Brown wrote:
Use type "bool" when you want a boolean. It is /not/ the same as an
int ...
You seem to be saying that something like
bool a = b == c;
should not be allowed.
David Brown <david.brown@hesbynett.no> writes:
On 11/02/2024 02:08, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 16:58:01 +0100, David Brown wrote:The type of c == d is int, but the value will be either 0 or 1. Is
It says "Assignment operators shall not be used in expressions which >>>>> return Boolean values", at least in my copy of MISRA 1998.
One thing with that wording, it would disallow chained assignments in such >>>> innocuous cases as
a = b = c == d;
since, after all, the expression is returning a boolean.
that
what you mean by an expression "returning a boolean" -- an expression of >>> type in with either 0 or 1 as the value?
I think that is what MISRA means when they talk about "essentially
boolean" - but as I mentioned before, they don't define the term at
all. (MISRA 2012 supports C99, and also appears to consider _Bool as
"essentially boolean", despite not defining it.)
I'll note that the requirement "Assignment operators shall not be used
in expressions which return Boolean values" doesn't use the (undefined)
term "essentially Boolean".
If it's intended to refer to "essentially Boolean" values, and if it
means what you suggest, then the guideline would permit this:
char c = ...;
int uc;
if (uc = isupper(c)) ...
since isupper() is specified to return zero or non-zero, not zero or
one. (It would be disallowed by the later version of MISRA which bans
any use of the result of an assignment expression.)
The only way the term "boolean" or "essentially Boolean" makes sense is
if it refers to *conditions*.
On 12/02/2024 12:38, bart wrote:
On 12/02/2024 11:26, David Brown wrote:
Absolutely. There is a /massive/ difference between:
int * p;
I assume the * is a typo?
No.
_Bool b = p;
This is equivalent to "b = (p != NULL);" and does not elicit a warning
from gcc (-Wall -Wextra -Wpedantic -std=C11).
(You might feel that there /should/ be a warning about it - that's
another matter. I'm saying what gcc does here, not what I think it
should do.)
and
int x = p;
This will set "x" to an integer value based on the pointer's address. It
is almost certainly not something the programmer wanted, and elicits a warning from gcc even without any options.
The point is, "_Bool" and "int" are not only different in theory (as
Keith has said several times, they are different incompatible types),
but they are different in practice.
(I don't know if your compiler has support for _Bool at all.)
On 12/02/2024 11:26, David Brown wrote:
On 12/02/2024 04:34, Keith Thompson wrote:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sat, 10 Feb 2024 21:37:26 -0800, Keith Thompson wrote:
_Bool is a distinct type. Equality and relational operators yield >>>>>> results of type int, which is not type _Bool.
There is no place where one type can be used, but the other cannot.
Incorrect.
int main(void) {
_Bool b;
int i;
_Bool *ptr = &i;
// constraint violation because _Bool and int are not compatible >>>> }
Do you understand that int and _Bool are distinct and incompatible
types, and that neither is a "subtype" of the other?
Oh, and conversion from any scalar type to _Bool yields either (_Bool)0
or (_Bool)1, a major difference between _Bool and all other scalar
types.
Absolutely. There is a /massive/ difference between:
int * p;
I assume the * is a typo?
_Bool b = p;
and
int x = p;
On 12/02/2024 13:36, David Brown wrote:
On 12/02/2024 12:38, bart wrote:
On 12/02/2024 11:26, David Brown wrote:
Absolutely. There is a /massive/ difference between:
int * p;
I assume the * is a typo?
No.
_Bool b = p;
This is equivalent to "b = (p != NULL);" and does not elicit a warning
from gcc (-Wall -Wextra -Wpedantic -std=C11).
(You might feel that there /should/ be a warning about it - that's
another matter. I'm saying what gcc does here, not what I think it
should do.)
and
int x = p;
This will set "x" to an integer value based on the pointer's address.
It is almost certainly not something the programmer wanted, and
elicits a warning from gcc even without any options.
OK, at least one of them was wrong! I saw the warning for this one from
gcc; my compiler rejects both assignments.
The point is, "_Bool" and "int" are not only different in theory (as
Keith has said several times, they are different incompatible types),
but they are different in practice.
(I don't know if your compiler has support for _Bool at all.)
My C compiler has a _Bool type but it is just an alias for 'char'. (I
think done when 'char' was an alias for 'unsigned char', I later changed
it to 'signed char'.)
So it doesn't have any special properties; assigning p to it is an error
(it will need !!p), and assigning *p will copy the bottom 8 bits.
(However, if I do the same test in my systems language, there it works
as expected:
ref void p:=nil, q:=&p
bool b:=p, c:=q
println b, c, int(c)
It prints 'False True 1', which was a surprise as I must have forgotten
I'd done that support. I never use 'bool', it's more of an internal
type. But it means I could port some of this to the C compiler.)
David Brown <david.brown@hesbynett.no> writes:
On 12/02/2024 12:38, bart wrote:
On 12/02/2024 11:26, David Brown wrote:
On 12/02/2024 04:34, Keith Thompson wrote:I assume the * is a typo?
Oh, and conversion from any scalar type to _Bool yields either (_Bool)0 >>>>> or (_Bool)1, a major difference between _Bool and all other scalar
types.
Absolutely. There is a /massive/ difference between:
int * p;
No.
_Bool b = p;
This is equivalent to "b = (p != NULL);" and does not elicit a warning
from gcc (-Wall -Wextra -Wpedantic -std=C11).
(You might feel that there /should/ be a warning about it - that's
another matter. I'm saying what gcc does here, not what I think it
should do.)
and
int x = p;
This will set "x" to an integer value based on the pointer's
address. It is almost certainly not something the programmer wanted,
and elicits a warning from gcc even without any options.
This is a constraint violation. A compiler that doesn't reject it
*might* generate code that behaves as you suggest.
On 12/02/2024 11:40, David Brown wrote:
On 11/02/2024 19:00, Malcolm McLean wrote:The "C installation " is not a rigorously defined concept and can be
That is why C99 calls the type "_Bool", and you need to include
<stdbool.h> to get the nicer name "bool". Now with C23, the C
standards committee feel confident that the proportion of code that
used "bool" for their own types is small enough that it is safe to
make "bool", "true" and "false" keywords.
And it is why it is insane to suggest that it is a good idea to make
your own pseudo-boolean type in C and call it "bool". It was a
questionable idea in the late nineties when C99 was known to be coming
soon, a bad idea in the early naughties when it had been published and
compiler support was gaining, and is certainly not an acceptable idea
now.
A simple typedef bool "bool" to "int" and definiing "true" and
"false" creates problems because there are no namespaces, you export
the symbols, and either they clash or they create mismash of subtly
different Boolean types.
Correct.
So I am not recommending it in user code.
Then what were you doing when you wrote this?
"""
You can achieve most of the benefits of a boolean type by aliasing >> "int' to "bool" and defining "true" and "false", and a lot of C
installations do exactly this.
"""
However I am saying that it does achieve most of the benefits of
having a boolean type, and therefore people who do this are not
entirely stupid. But I'm talking about the C installation, so
normally the person who provides the compiler, not the user code.
And what is a "C installation" ? Do you mean a "C /implementation/" ?
Do you mean your own modification to headers or libraries after you
have installed a toolchain? Do you mean a company's standard
additional libraries?
Or do you mean that C implementations simply put "typedef int bool;"
as their <stdbool.h> implementation? That would, of course, be utter
nonsense.
thought of as a fuzzy set. But basically it means someone who provides
both the compiler and a library which must be used on that platform, and therefore has a similar status to the standard library, but just for
that platform.
So for example Mircrosoft provide a file called "windef.h" which
contains the following declarations.
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
They use upper case. But otherwise it's exactly as I stated.
In my view
this is reasonable. But it wouldn't be reasonable in a libarary designed
to do fast Fiurier transforms, for example. It's reasonable because
windef.h is part of the "C installation".
On 13/02/2024 08:07, David Brown wrote:
On 12/02/2024 21:27, Malcolm McLean wrote:
The "C installation " is not a rigorously defined concept and can be
thought of as a fuzzy set. But basically it means someone who
provides both the compiler and a library which must be used on that
platform, and therefore has a similar status to the standard library,
but just for that platform.
That would be the "C implementation", and it /is/ a well-established
term. It would be helpful if you used the standard terms here.
The "C implentation" would be be the program created by the person who
writes the complier.
The "C installation" the system set up by the
person who provides the compiler.
Often one and the same, but not
necessarily. You can have a compiler written by someone else and an API written by someone else, put them together, and say "this shall be what
we use to create C programs for this platform". So you have set up the C installation, but you are not the implementor.
Yes, and it's a nightmare, because whilst it's obvious that anSo for example Mircrosoft provide a file called "windef.h" which
contains the following declarations.
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
None of that defines "bool", "true" or "false". This is /very/
different.
It is a typical pre-C99 pseudo-boolean, and made sense before C99.
The "windef.h" file needs to keep these for compatibility, especially
in light of MS's notoriously poor and late C99 support, but no one
should consider using them for anything now except as required for
compatibility with external code that has them. (For example, if you
are calling a function that takes a "BOOL *" pointer, you can't
replace that with a "bool *" pointer.)
They use upper case. But otherwise it's exactly as I stated.
And the upper case makes all the difference. As far as C is
concerned, and as far as any trained C programmer is concerned, the
difference is perfectly clear. Windows has a convention in its API
and windef.h and windows.h headers of using all-caps names for locally
defined type names that are specific and consistent for all Windows
versions, and don't change according to the processor type - things
like BYTE and LONG have existed from 16-bit Windows, through 32-bit
and 64-bit Windows. They are not easily mistaken for the C standard
types.
In my view this is reasonable. But it wouldn't be reasonable in a
libarary designed to do fast Fiurier transforms, for example. It's
reasonable because windef.h is part of the "C installation".
I agree that this was a reasonable practice from MS, prior to C99. I
wish they had moved over to C99 types like "bool" and the sized
integer types (int32_t, etc.) as soon as these were standardised,
keeping the old all-caps types only for compatibility with old code,
and deprecating them as soon as reasonably possible. But prior to C99
they couldn't really have done much better. And I agree that a major
C implementation, and the nearest Windows has to standard platform
headers, can reasonably claim generic names like BOOL.
It is normal for C90 libraries to have their own types for things like
booleans, but they should be named with prefixes like the rest of the
library - so you might have "fft_Boolean". Of course, anything this
century should be in at least C99 and use standard types, but this
kind of thing still hangs around because some code stretches back to
last century.
fft_boolean is a variable which is meant to represent "true" or "false",
it's not so obvious where code which calls but does not implement the
Fourier transforms should use it, and it might not even be binary
compatible with other types in the program designed to do the same
thing. A standrd atype is blessing, and all you really need for that is
a simple standard header declaring "bool" as a type, and "true" and
"false" as constants. Now "false" must be zero, But should "true" be 1
or -1?
But these types are /not/ a substitute for standard C bool. TheyI discussed using Pico C to implement a build system recently. Now I
don't do the same thing. They are not as good. They are not as
standard. They were the best be had a generation ago, but there is no
reason to use them now except for interfacing with old code, and
certainly no reason to consider defining a new home-made boolean.
have't checked, but it's not fully featured and I don't think it
supports coercing a boolean to be 1 or 0. But by providing a trivial
header we could get most C source which uses "bool" to interpret
correctly. And that would be a lot easier than trying to modify the interpeter. Of course
char *ptr = something();
bool flag = (bool) ptr;
if (flag == true)
will not be interpreted correctly. But we can live with that.
The Pico C would be our "C installation" by the way.
We wouldn't claim
to be the implenters. Not every word has to have been used before in
exactly the same context to be used correctly, as you seem to think.
(Now let's start a flame war because I did English at Oxford whilst you didn't).
On 13/02/2024 10:35, Malcolm McLean wrote:
On 13/02/2024 08:07, David Brown wrote:
The "C implentation" would be be the program created by the person who
writes the complier.
No, that would be the compiler.
The "C implementation" includes the compiler, associated tools like assemblers and linkers, headers, the standard C library, and parts of
the target system that are needed in order to execute the program.
The "C installation" the system set up by the person who provides the
compiler.
I am trying to understand what you mean by this - as usual, it is not
easy as you insist on using your own invented terms in your own way, and
have great difficultly explaining them to others.
Maybe you are talking about what others might refer to as a "toolchain",
Often one and the same, but not necessarily. You can have a compiler
written by someone else and an API written by someone else, put them
together, and say "this shall be what we use to create C programs for
this platform". So you have set up the C installation, but you are not
the implementor.
The term "C implementation" is not connected to who makes the compiler, library, installation packages or anything else. It's a /thing/, not a person or group, and it is the characteristics of the C implementation
that are important, not where it came from.
Yes, a standard boolean type is an extremely important feature in a programming language. The fact that C did not have one until C99 has resulted in a great deal of inconvenience and wasted effort. Then in
1999, we got a standard boolean type in C. Use it! No, it is not sufficient to have a "typedef int bool" in a header to make a /good/
boolean type. No, "true" should not be -1. No, you should never define your own type "bool".
will not be interpreted correctly. But we can live with that.
We can live with all kinds of things - that does not mean we /should/
live with it.
Pico C appears to be a dead project. And it was never intended to be
more than a tiny handler for a subset of C - of unspecified version, and without any attempt at conformance. It's broken version of <stdbool.h>
is dangerously wrong and has no place in anything that claims to call
itself "C" or "C-like". It should be either fixed, or removed entirely.
But as it is a dead project there is little point in reporting the error.
The Pico C would be our "C installation" by the way.
Or, to use the correct term, the "C implementation". Or perhaps the "Sort-of C implementation".
On 13/02/2024 10:36, David Brown wrote:
On 13/02/2024 10:35, Malcolm McLean wrote:Now this sort of thing irritates some of the others, and so I shouldn't
I am trying to understand what you mean by this - as usual, it is not
easy as you insist on using your own invented terms in your own way,
and have great difficultly explaining them to others.
have to explain and justify to some people the basics of how to use the English language.
Yes, can be the second. Embedded developers talk about "toolchains" but non-embedded developers mostly don't, and it's not really relevant that
But you might also be talking about a customised setup, either done by
an individual on their own systems, or by a company wanting all their
developers to have the same development environment.
in a typical C implemntation several programs are run to create the exectuable instead of only one. But it is relevant that all the
developers have the same development environment. If everyone shall use "BOOL" rather than "bool" because that is the customised common header
chosen by the company, that's exactly what I am talking about.
"Have you stopped beating your wife?"
Yes, and it's a nightmare, because whilst it's obvious that an
fft_boolean is a variable which is meant to represent "true" or
"false", it's not so obvious where code which calls but does not
implement the Fourier transforms should use it, and it might not even
be binary compatible with other types in the program designed to do
the same thing. A standrd atype is blessing, and all you really need
for that is a simple standard header declaring "bool" as a type, and
"true" and "false" as constants. Now "false" must be zero, But should
"true" be 1 or -1?
Have you been living under a rock for the last 25 years? Do you write
code for the OCCC, or are you aiming for a "featured article" in the
Daily WTF?
<https://thedailywtf.com/articles/what_is_truth_0x3f_>
<https://thedailywtf.com/articles/Extra-Boolean>
True / false often isn't adequate.
Yes, a standard boolean type is an extremely important feature in atrue can be -1 in boolean logic.
programming language. The fact that C did not have one until C99 has
resulted in a great deal of inconvenience and wasted effort. Then in
1999, we got a standard boolean type in C. Use it! No, it is not
sufficient to have a "typedef int bool" in a header to make a /good/
boolean type. No, "true" should not be -1. No, you should never
define your own type "bool".
The real reason is that -1 is all bits
set, so ~true == false. But of course a one bit number is either -1 or 0
in two;s complement notation.
However someone has to take decsion on this and there should be one
standard, I totally agree.
There aren't that many open source, free to use C intepreters hanging
Pico C appears to be a dead project. And it was never intended to be
more than a tiny handler for a subset of C - of unspecified version,
and without any attempt at conformance. It's broken version of
<stdbool.h> is dangerously wrong and has no place in anything that
claims to call itself "C" or "C-like". It should be either fixed, or
removed entirely. But as it is a dead project there is little point
in reporting the error.
around.
On 13/02/2024 10:36, David Brown wrote:
On 13/02/2024 10:35, Malcolm McLean wrote:
On 13/02/2024 08:07, David Brown wrote:
The "C implentation" would be be the program created by the person whoNo, that would be the compiler.
writes the complier.
The "C implementation" includes the compiler, associated tools like
assemblers and linkers, headers, the standard C library, and parts of the
target system that are needed in order to execute the program.
The "C installation" the system set up by the person who provides theI am trying to understand what you mean by this - as usual, it is not
compiler.
easy as you insist on using your own invented terms in your own way, and
have great difficultly explaining them to others.
Maybe you are talking about what others might refer to as a "toolchain",
It seems clear to me what the difference is between installation and implementation.
A factory implements a washing machine, and somebody else decides where to install it in their house and how and to what it is hooked up.
On 13/02/2024 10:36, David Brown wrote:
On 13/02/2024 10:35, Malcolm McLean wrote:
On 13/02/2024 08:07, David Brown wrote:
The "C implentation" would be be the program created by the person
who writes the complier.
No, that would be the compiler.
The "C implementation" includes the compiler, associated tools like
assemblers and linkers, headers, the standard C library, and parts of
the target system that are needed in order to execute the program.
The "C installation" the system set up by the person who provides the
compiler.
I am trying to understand what you mean by this - as usual, it is not
easy as you insist on using your own invented terms in your own way,
and have great difficultly explaining them to others.
Maybe you are talking about what others might refer to as a "toolchain",
It seems clear to me what the difference is between installation and implementation.
A factory implements a washing machine, and somebody else decides where
to install it in their house and how and to what it is hooked up.
Often one and the same, but not necessarily. You can have a compiler
written by someone else and an API written by someone else, put them
together, and say "this shall be what we use to create C programs for
this platform". So you have set up the C installation, but you are
not the implementor.
The term "C implementation" is not connected to who makes the
compiler, library, installation packages or anything else. It's a
/thing/, not a person or group, and it is the characteristics of the C
implementation that are important, not where it came from.
So it just 'exists' without anyone having created it?
Yes, a standard boolean type is an extremely important feature in a
programming language. The fact that C did not have one until C99 has
resulted in a great deal of inconvenience and wasted effort. Then in
1999, we got a standard boolean type in C. Use it! No, it is not
sufficient to have a "typedef int bool" in a header to make a /good/
boolean type. No, "true" should not be -1. No, you should never
define your own type "bool".
It's not /that/ important. The concept is more important than having a dedicated type.
I added a proper boolean type to my scripting language at one point.
Then I streamlined it and got rid of it.
There is an `integer` type which can represent a million different kinds
of things; why make a special type for a thing that has the values of 0
or 1?
(In dynamic code, extra types mean spending longer doing runtime type checking.)
A proper _Bool type gives the possibility of arrays of _Bools that
occupy one bit per element. However that doesn't happen here:
_Bool A[1024];
printf("%zu\n", sizeof(A));
I get '1024' with gcc -O3, not 128. (My scripting language, despite not having Bool, does have 1-bit arrays. Those can be more useful.)
will not be interpreted correctly. But we can live with that.
We can live with all kinds of things - that does not mean we /should/
live with it.
Pico C appears to be a dead project. And it was never intended to be
more than a tiny handler for a subset of C - of unspecified version,
and without any attempt at conformance. It's broken version of
<stdbool.h> is dangerously wrong and has no place in anything that
claims to call itself "C" or "C-like". It should be either fixed, or
removed entirely.
You're fond of saying that.
But as it is a dead project there is little point in reporting the
error.
The Pico C would be our "C installation" by the way.
Or, to use the correct term, the "C implementation". Or perhaps the
"Sort-of C implementation".
Even C++ is a 'sort-of-C' implementation.
Suppose you have a C program that uses 85% of the features of C. You use
a C compiler which only implements that same 85% subset. Your program
works perfectly.
But I guess you would still look down your knows at such a product?
Some C compilers implement a subset of the language, some a superset. I expect a superset is fine? But neither are actually C!
And of course, using compiler options to further customise the language
is also acceptable.
"PicoC is a very small C interpreter for scripting. It was originally
written as the script language for a UAV's on-board flight system. It's
also very suitable for other robotic, embedded and non-embedded applications."
Do you object to its use of "C"?
I suggest that the bug of using "=" where "==" was intended occurs
almost exclusively among inexperienced C programmers, particularly those
who are inexperienced with programming in general.
It's a mistake that's made because the programmer assumes that "="
is a comparison operator, as it is in mathematics and in some other programming languages.
It's an easy and understandable mistake
to make, but any reasonably experienced C programmer will have
internalized the fact that "=" means assignment, not comparison.
To a newbie, `if (x = y)` *looks like* a comparison. To an
experienced C programmer it doesn't.
(It's possible I'm overgeneralizing. For example, a programmer who
commonly switches between C and other languages might still mix up "="
and "==" occasionally.)
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come up, because ":=" doesn't look like a comparison even to a newbie. But it's
far too late to fix that in any language called "C".
[...]
There are plenty of coding standards which ban the use of the results of assignment expressions, and I think there is little doubt that stricter coding standards reduce at least some kinds of errors in code. But it
would be impossible to isolate the effect of one particular rule.
If someone knows about such studies, it would be great to hear about
them - failing that, guesses and gut feelings based on personal
experience is about as good as we can get.
In MISRA 1998, the explanation for that rule includes:
"""
Strictly speaking, in C, there is no Boolean type, but there is a
conceptual difference between expressions which return a numeric value
and expressions which return a Boolean value.
If assignments are required then they must be performed separately
outside of any expressions which are effectively of Boolean type.
"""
MISRA regularly uses its own terms that are different from the Standard
C terms, which IMHO is needlessly confusing and inaccurate. Sometimes
these terms are defined, sometimes not. "Boolean" and "Effectively
Boolean value" are not defined anywhere in MISRA 1998.
[...]
You seem to be saying that something like
bool a = b == c;
should not be allowed.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
https://www.stroustrup.com/JSF-AV-rules.pdf
Yes, and?
That's a 141-page PDF document with rules for C++. Did you want to say something about it?
On 11.02.2024 18:05, David Brown wrote:
Yes, we all know that. (Well, everyone who has learned a bit of C99
knows that.) It's very difficult to change things in a language that
has as much use as C - changing the type of the value of expressions
like "x == y" would have been a breaking change. When C++ was forked
from C, it was able to make such breaking changes - thus "x == y" gives
a bool in C++. But for C, it was too late.
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
On 11.02.2024 18:05, David Brown wrote:
Yes, we all know that. (Well, everyone who has learned a bit of C99
knows that.) It's very difficult to change things in a language
that has as much use as C - changing the type of the value of
expressions like "x == y" would have been a breaking change. When
C++ was forked from C, it was able to make such breaking changes -
thus "x == y" gives a bool in C++. But for C, it was too late.
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
Janis
[...] They had been trying to rule out "if (x = y)"
and requiring it to be written "x = y; if (x != 0) ...".
On 09/02/2024 16:43, bart wrote:
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a, b, c
all having different numerical types.
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come up, because ":=" doesn't look like a comparison even to a newbie. But
it's far too late to fix that in any language called "C".
On 11.02.2024 13:57, David Brown wrote:
[...] They had been trying to rule out "if (x = y)"
and requiring it to be written "x = y; if (x != 0) ...".
One could of course also have written it as
if (x = y) // this is intentionally an assignment!
Sometimes a comment is better than asking to rewrite the code.
On 13/02/2024 14:10, David Brown wrote:
On 13/02/2024 13:32, bart wrote:So this is how they do it.
"PicoC is a very small C interpreter for scripting. It was originally
written as the script language for a UAV's on-board flight system.
It's also very suitable for other robotic, embedded and non-embedded
applications."
Do you object to its use of "C"?
I don't know if it is close enough to some version of C for it to be
reasonable to call it a "C compiler" (or "C interpreter") without
qualification. I haven't looked at it in any kind of detail. But I
/do/ know it has a <stdbool.h> header that most certainly does not
define a C "bool" type, and I see that as a problem. In particular,
it is a pointless problem - it serves no purpose, but could cause
subtle problems when used with code that is correct and conforming C,
tested and debugged with other implementations.
/* string.h library for large systems - small embedded systems use
clibrary.c instead */
#include "../interpreter.h"
#ifndef BUILTIN_MINI_STDLIB
static int trueValue = 1;
static int falseValue = 0;
/* structure definitions */
const char StdboolDefs[] = "typedef int bool;";
/* creates various system-dependent definitions */
void StdboolSetupFunc(Picoc *pc)
{
/* defines */
VariableDefinePlatformVar(pc, NULL, "true", &pc->IntType, (union AnyValue *)&trueValue, FALSE);
VariableDefinePlatformVar(pc, NULL, "false", &pc->IntType, (union AnyValue *)&falseValue, FALSE);
VariableDefinePlatformVar(pc, NULL,
"__bool_true_false_are_defined", &pc->IntType, (union AnyValue
*)&trueValue, FALSE);
}
#endif /* !BUILTIN_MINI_STDLIB */
Whilst I have't actually checked, presumably the interpreter calls StdBoolSetUpFunc() when it hits "#include <stdbool.h>", and that puts variables called "true" and "false" which are ints into global scope,
plus another int (not a boolean ironically) to flag that the function
has been called. Somehow the typedef is picked up elsewhere.
That does not mean that it is not a useful tool. But it would, IMHO,Now this means that the vast majority of code which is sanely written
be a /better/ tool if that header were simply omitted entirely.
and uses "stdbool.h", but isn't written specifically for Pico C, will be interpreted correctly.
But an tiny amount may break. And if it is
running on a UAV which is armed with a nuclear missile, that may be a
bit alarming. But mostly it won't be, and it will be fine.
On Fri, 09 Feb 2024 09:09:41 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come up,
because ":=" doesn't look like a comparison even to a newbie. But
it's far too late to fix that in any language called "C".
If DMR ever considered := for assignment then it probably lasted no
longer than it took him to pay attention that in order to type ':' on
the standard keyboard one has to press shift.
But boolean is a subtype of int anyway, so what’s the harm in redefining conditional expressions to return bool instead?
On Fri, 9 Feb 2024 19:47:45 -0000 (UTC), Blue-Maned_Hawk wrote:
There are too many situations where assignment being an expression is a
useful facet of the language; i am not willing to sacrifice that for an
ill-defined ideal of “safety”.
If you consider it “ill-defined”, consider the number of people who have developed the habit of writing
if (NULL == p) ...
instead of the more natural
if (p == NULL) ...
On 09/02/2024 16:43, bart wrote:
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a, b,
c all having different numerical types.
To *ban* something because it is confusing to you?
Thus adding inconsistencies to the language?
What is it that confuses you? - I am assuming you know the operator precedence rules, and that x += y like x = y returns a value?
Does using parenthesis to sort things maybe help you?
Janis
On Tue, 13 Feb 2024 17:29:43 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 09/02/2024 16:43, bart wrote:
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a, b,
c all having different numerical types.
To *ban* something because it is confusing to you?
Thus adding inconsistencies to the language?
What is it that confuses you? - I am assuming you know the operator
precedence rules, and that x += y like x = y returns a value?
Does using parenthesis to sort things maybe help you?
Janis
It's actually highly confusing for me as well.
For reasons I am not fully understand, it is interpreted as
a += (b += c)
which is obviously legal.
I don't understand why it isn't interpreted as
(a += b) += c
which is [a little less obviously] illegal.
On Tue, 13 Feb 2024 17:29:43 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 09/02/2024 16:43, bart wrote:
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a, b,
c all having different numerical types.
To *ban* something because it is confusing to you?
Thus adding inconsistencies to the language?
What is it that confuses you? - I am assuming you know the operator
precedence rules, and that x += y like x = y returns a value?
Does using parenthesis to sort things maybe help you?
Janis
It's actually highly confusing for me as well.
For reasons I am not fully understand, it is interpreted as
a += (b += c)
which is obviously legal.
I don't understand why it isn't interpreted as
(a += b) += c
which is [a little less obviously] illegal.
Seems like += associates from right to left, same like =.
IMHO, it would have been more natural if it was associating from left
to right, like + most other operators.
Michael S <already5chosen@yahoo.com> writes:
On Fri, 09 Feb 2024 09:09:41 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come
up, because ":=" doesn't look like a comparison even to a newbie.
But it's far too late to fix that in any language called "C".
If DMR ever considered := for assignment then it probably lasted no
longer than it took him to pay attention that in order to type ':' on
the standard keyboard one has to press shift.
The keyboard DMR used when developing C did not require shift
to type a colon.
https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg
On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:
On Tue, 13 Feb 2024 17:29:43 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 09/02/2024 16:43, bart wrote:
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a,
b, c all having different numerical types.
To *ban* something because it is confusing to you?
Thus adding inconsistencies to the language?
What is it that confuses you? - I am assuming you know the operator
precedence rules, and that x += y like x = y returns a value?
Does using parenthesis to sort things maybe help you?
Janis
It's actually highly confusing for me as well.
For reasons I am not fully understand, it is interpreted as
a += (b += c)
which is obviously legal.
I don't understand why it isn't interpreted as
(a += b) += c
which is [a little less obviously] illegal.
In C, all the assignment operators are defined to associate
right to left. That's why
a += b += c;
evaluates as if it were expressed as
a += (b += c);
Seems like += associates from right to left, same like =.
IMHO, it would have been more natural if it was associating from
left to right, like + most other operators.
But, += is an assignment operator, not an operator in the (+ -) group.
And, you want /assignments/ to associate right to left, otherwise
a = b;
would assign the value of a to the lval b
On Tue, 13 Feb 2024 17:33:00 -0000 (UTC)[snip]
Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:
Seems like += associates from right to left, same like =.
IMHO, it would have been more natural if it was associating from
left to right, like + most other operators.
But, += is an assignment operator, not an operator in the (+ -) group.
And, you want /assignments/ to associate right to left, otherwise
a = b;
would assign the value of a to the lval b
Yes, I want simple assignment operator to associate right to left.
But I'd rather prefer for it to be an only exception to left to right
rule.
On Tue, 13 Feb 2024 17:29:43 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 09/02/2024 16:43, bart wrote:
What I wouldn't care about banning however is this:
a += b += c;
Because it's just confusing. If you don't think so, consider a, b,
c all having different numerical types.
To *ban* something because it is confusing to you?
Thus adding inconsistencies to the language?
What is it that confuses you? - I am assuming you know the operator
precedence rules, and that x += y like x = y returns a value?
Does using parenthesis to sort things maybe help you?
Janis
It's actually highly confusing for me as well.
For reasons I am not fully understand, it is interpreted as
a += (b += c)
which is obviously legal.
I don't understand why it isn't interpreted as
(a += b) += c
which is [a little less obviously] illegal.
Seems like += associates from right to left, same like =.
IMHO, it would have been more natural if it was associating from left
to right, like + most other operators.
On 13/02/2024 16:30, David Brown wrote:
On 13/02/2024 16:20, Malcolm McLean wrote:
Pico C won't coerce a boolean to 1 or 0. Whilst it's easy t deviseNow this means that the vast majority of code which is sanely written
and uses "stdbool.h", but isn't written specifically for Pico C, will
be interpreted correctly.
That is not true.
Code that relies on "bool" values being 0 or 1 is perfectly "sane",
and will not work with the broken "bool" in Pico C.
perfectly legal C code where this matters, it's less easy to think of an example which could also be defended as "sane".
Code that uses "bool b = p;", where "p" is a pointer, is perfectlyThough that is an exception. A null pointer is conventionally "not
sane and may not work if Pico C correctly complains about the
constraint error from "int b = p;".
there", and so it's reasonable for null / not null to be boolean.
However bool b = p; still isn't very good. It should be bool b = p ?
true : false; to make it explicit.>
It is true that a lot of code that uses "bool", "true" and "false"it won;t fail subty an donly in some circumstances.
will work in the face of "typedef int bool". It is also true that
some will not - and there was nothing wrong or insane about the code.
Such code may fail subtly with Pico C, and only in some
circumstances. People using it will have to check their code, and
change anything of the form "bool b = x;" into "bool b = !!x;" to be
sure.
And if we rip out stdbool.h support, none of the code wll work. However
Well you don't seem to understand the realities of it. I'm sure I've the skills to patch Pico C to have a real boolean type which only has one
But an tiny amount may break. And if it is running on a UAV which is
armed with a nuclear missile, that may be a bit alarming. But mostly
it won't be, and it will be fine.
I am not at ease with an attitude of "There's a completely
unnecessary, known and easily fixable mistake in this software, but
hopefully you won't be using the tool for anything too serious and
won't have many problems". That is simply not how a programmer should
think.
bit. But I can't do that quickly or easily. And Pico C is not under
active development, and they say it is frozen and they want to keep it
small. It's likely that no-one will accept the pull request. So now our
Pico C has diverged from the trunk, and that causes issues. And a lot of programs are not too serious, or the costs of bugs are not too high.
On 13/02/2024 16:30, David Brown wrote:
The Baby
X resource compiler needs a way of converting a pixel value to an
arbitrary output format, and my current answer to that is "you are a C >programmer,
On Tue, 13 Feb 2024 19:49:28 +0200, Michael S wrote:
On Tue, 13 Feb 2024 17:33:00 -0000 (UTC)
Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
[snip]On Tue, 13 Feb 2024 19:22:57 +0200, Michael S wrote:
Seems like += associates from right to left, same like =.
IMHO, it would have been more natural if it was associating from
left to right, like + most other operators.
But, += is an assignment operator, not an operator in the (+ -)
group. And, you want /assignments/ to associate right to left,
otherwise a = b;
would assign the value of a to the lval b
Yes, I want simple assignment operator to associate right to left.
But I'd rather prefer for it to be an only exception to left to
right rule.
Then you would eliminate the unary operators (! ~ ++ -- and others)
then? If not, how would you handle them, as they also associate right-to-left.
On Tue, 13 Feb 2024 17:06:00 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
Michael S <already5chosen@yahoo.com> writes:
On Fri, 09 Feb 2024 09:09:41 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
If C had used ":=" for assignment and "=" for comparison (and "=="
probably not used for anything), the problem would never have come
up, because ":=" doesn't look like a comparison even to a newbie.
But it's far too late to fix that in any language called "C".
If DMR ever considered := for assignment then it probably lasted no
longer than it took him to pay attention that in order to type ':' on
the standard keyboard one has to press shift.
The keyboard DMR used when developing C did not require shift
to type a colon.
https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg
WOW, that's extremely surprising for me.
Not a ':' but that they developed C and Unix with keyboard that can't
even type lower case characters.
On Tue, 13 Feb 2024 17:06:00 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg
WOW, that's extremely surprising for me.
Not a ':' but that they developed C and Unix with keyboard that can't
even type lower case characters.
Actually, it's so surprising that worth clarification from somebody
that was around there. Do you have relevant contacts?
On Tue, 13 Feb 2024 17:06:00 GMT[snip]
scott@slp53.sl.home (Scott Lurndal) wrote:
The keyboard DMR used when developing C did not require shift
to type a colon.
https://en.wikipedia.org/wiki/Teletype_Model_33#/media/File:Mappa_Teletype_ASR-33.jpg
WOW, that's extremely surprising for me.
Not a ':' but that they developed C and Unix with keyboard that can't
even type lower case characters.
Actually, it's so surprising that worth clarification from somebody
that was around there. Do you have relevant contacts?
On 13/02/2024 18:27, Scott Lurndal wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
On 13/02/2024 16:30, David Brown wrote:
The Baby
X resource compiler needs a way of converting a pixel value to an
arbitrary output format, and my current answer to that is "you are a C
programmer,
Mine answer would be to use netpbm rather than reinventing the wheel
for the Nth time.
I checked that out.
This is the relevant program.
https://netpbm.sourceforge.net/doc/ppmtoarbtxt.html
I have the habit to write such specific expressions with parenthesis
a = (b == c);
for own convenience or better maintainability. (Just BTW.)
On 13/02/2024 19:54, Malcolm McLean wrote:
On 13/02/2024 18:27, Scott Lurndal wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
On 13/02/2024 16:30, David Brown wrote:
The Baby
X resource compiler needs a way of converting a pixel value to an
arbitrary output format, and my current answer to that is "you are a C >>>> programmer,
Mine answer would be to use netpbm rather than reinventing the wheel
for the Nth time.
I checked that out.
This is the relevant program.
https://netpbm.sourceforge.net/doc/ppmtoarbtxt.html
No, that's not Linux-centric at all!
On Tue, 13 Feb 2024 17:00:00 +0100, Janis Papanagnou wrote:
I have the habit to write such specific expressions with parenthesis
a = (b == c);
for own convenience or better maintainability. (Just BTW.)
Parenthesis clutter seems to be a common affliction among C programmers.
Why not just keep the docs handy, so you can check the precedences if in >doubt?
dstval =
((uint32_t *)dstrow)[col]
&
~((1 << dst.bitwidth) - 1 << dst.shiftoffset)
|
srcval << dst.shiftoffset;
bart <bc@freeuk.com> writes:
On 13/02/2024 19:54, Malcolm McLean wrote:
On 13/02/2024 18:27, Scott Lurndal wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
On 13/02/2024 16:30, David Brown wrote:
The Baby
X resource compiler needs a way of converting a pixel value to an
arbitrary output format, and my current answer to that is "you are a C >>>>> programmer,
Mine answer would be to use netpbm rather than reinventing the wheel
for the Nth time.
I checked that out.
This is the relevant program.
https://netpbm.sourceforge.net/doc/ppmtoarbtxt.html
No, that's not Linux-centric at all!
It predates linux and ran on dozens of unix variants.
<deleted another bart rant>
On Tue, 13 Feb 2024 16:55:32 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
Pre-history vs history.
As far as I am concerned, 'initially' == it presents in in the first
edition of "The C++ Programming Language".
On Tue, 13 Feb 2024 17:00:00 +0100, Janis Papanagnou wrote:
I have the habit to write such specific expressions with parenthesis
a = (b == c);
for own convenience or better maintainability. (Just BTW.)
Parenthesis clutter seems to be a common affliction among C programmers.
On 13/02/2024 16:55, Janis Papanagnou wrote:
On 11.02.2024 18:05, David Brown wrote:
Yes, we all know that. (Well, everyone who has learned a bit of C99
knows that.) It's very difficult to change things in a language that
has as much use as C - changing the type of the value of expressions
like "x == y" would have been a breaking change. When C++ was forked
from C, it was able to make such breaking changes - thus "x == y" gives
a bool in C++. But for C, it was too late.
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
It was there from the first standard version of C++.
[...] But you are correct that it did
not exist in early drafts of C++ prior to standardisation.
On 14.02.2024 00:36, Janis Papanagnou wrote:
On 13.02.2024 17:11, Michael S wrote:
As far as I am concerned, 'initially' == it presents in in the first
edition of "The C++ Programming Language".
[...] don't recall that it had described the bool type. [...]
Can anyone confirm or falsify whether the 'bool' type was already
part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.
On 13.02.2024 17:11, Michael S wrote:
As far as I am concerned, 'initially' == it presents in in the first
edition of "The C++ Programming Language".
[...] don't recall that it had described the bool type. [...]
On 13/02/2024 17:14, Janis Papanagnou wrote:
On 11.02.2024 13:57, David Brown wrote:
[...] They had been trying to rule out "if (x = y)"
and requiring it to be written "x = y; if (x != 0) ...".
One could of course also have written it as
if (x = y) // this is intentionally an assignment!
Sometimes a comment is better than asking to rewrite the code.
That is sometimes the case, but not here.
It is better to write the code clearly than to have a comment explaining
why you have written code that looks odd.
On 14.02.2024 00:36, Janis Papanagnou wrote:
On 13.02.2024 17:11, Michael S wrote:
As far as I am concerned, 'initially' == it presents in in the first
edition of "The C++ Programming Language".
[...] don't recall that it had described the bool type. [...]
Can anyone confirm or falsify whether the 'bool' type was already
part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.
On 14.02.2024 00:36, Janis Papanagnou wrote:
On 13.02.2024 17:11, Michael S wrote:
As far as I am concerned, 'initially' == it presents in in the first
edition of "The C++ Programming Language".
[...] don't recall that it had described the bool type. [...]
Can anyone confirm or falsify whether the 'bool' type was already
part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.
On 13.02.2024 17:13, David Brown wrote:
On 13/02/2024 16:55, Janis Papanagnou wrote:
On 11.02.2024 18:05, David Brown wrote:
Yes, we all know that. (Well, everyone who has learned a bit of C99
knows that.) It's very difficult to change things in a language that
has as much use as C - changing the type of the value of expressions
like "x == y" would have been a breaking change. When C++ was forked
from C, it was able to make such breaking changes - thus "x == y" gives >>>> a bool in C++. But for C, it was too late.
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
It was there from the first standard version of C++.
And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?
Rather late. (I've had my professional C++ the decade before that.)
[...] But you are correct that it did
not exist in early drafts of C++ prior to standardisation.
More importantly it wasn't available in commercial C++ implementations.
Bool and other useful features came rather late, unfortunately.
On 13/02/2024 20:58, Keith Thompson wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:But if software is running on a UAV which carries nuclear missiles and something goes wrong, millions of people might be killed. Whilst if the software that I write for a living goes wrong the worst thing that can
[...]
Now this means that the vast majority of code which is sanely written
and uses "stdbool.h", but isn't written specifically for Pico C, will
be interpreted correctly. But an tiny amount may break. And if it is
running on a UAV which is armed with a nuclear missile, that may be a
bit alarming. But mostly it won't be, and it will be fine.
You're suggesting that correctness doesn't matter unless the software
controls nuclear missiles.
No. Even if that was hyperbole -- no.
happen on any plausible scenario is that an artist's drawing gets ruined
and my company's liability for that is limited to a hundred and twenty dollars. You do see the difference.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
On 13.02.2024 17:34, David Brown wrote:
On 13/02/2024 17:14, Janis Papanagnou wrote:
On 11.02.2024 13:57, David Brown wrote:
[...] They had been trying to rule out "if (x = y)"
and requiring it to be written "x = y; if (x != 0) ...".
One could of course also have written it as
if (x = y) // this is intentionally an assignment!
Sometimes a comment is better than asking to rewrite the code.
That is sometimes the case, but not here.
It is better to write the code clearly than to have a comment
explaining why you have written code that looks odd.
Is it odd? - After all it's a common code pattern.
But, yes. If in doubt you should choose some means to make
it clear. And if it's the separation for you, that's fine.
Myself I observed me using all three variants (separating,
idiomatic, and commenting), depending on the context.
Another option is:
if ((x = y))
It's not *inherently* obvious that this is a good idea, but it's the
idiom suggested by gcc: "warning: suggest parentheses around
assignment used as truth value [-Wparentheses]".
Though personally, I'd probably make the assignment the operand of a
larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Now I know that you think Bart should just use make. But let's say it's agreed to proceed with the system I proposed, which is a C interpeter to drive a build script. Now I suggested modifying one of Bart's own
compilers. But that's more difficult than I thought. So my second option
is Pico C. Now I think that is achievable. If there's sufficient
consensus that the system is worth producing, we can hook up Pico C and thrash out a support library, with the resources we have in this
newsgroup, from people who are likely to want to contribute.
Now if you think we shouldn't do that because of the danger of the
scripting system being used in a critical environment and an error in
the boolean or other component of Pico C propagating, then how do you
think that we should proceed?
On 2024-02-13, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
Can anyone confirm or falsify whether the 'bool' type was already
part of the 1st (1985) and/or the 2nd (1991) edition? - Thanks.
Some data points.
I'm looking at 1989 sources for Cfront. There is no bool, except
in the implemnentation of an early version of templates, which
defines a bool for itself as: enum bool { true, false }.
Cfront 3.0.3 from around 1996 has a header like this:
source/incl-master/const-headers/std_bool.h
in which this is found:
typedef int bool;
const bool false = 0;
const bool true = 1;
So no built-in bool type distinct from int in the last Cfront for which
you can find source code.
Your memory is basically right about bool not having existed in
a substantial way back in the day.
On 14/02/2024 10:11, David Brown wrote:
On 14/02/2024 10:34, Malcolm McLean wrote:
The whole point of using C s to get away from the ad hoc scripting
language that you don't use frequently enough to remember exactly how it works, and to use something familiar. So we do want a C interpreter, not
a "C-like interpreter" to add yet another language with its own quirks
to the mess which Bart has so correctly identiifed.
I would prefer most of all to see its flaws and non-conformitiesAnd that is at least a direction. And maybe even a proposal for a hobby project.
fixed. It should not be particularly hard to do.
But if you want to take Pico C and use it as it is, that's yourWell you can't have it both ways. Either it is irresponsible to use Pico
choice. I doubt if its issues would be much of a problem for your use
of it for build scripts.
C in a build scripting system or it is not. Surely you are not
suggesting that I would choose to act irresponsibly purely because I
have a legal right to do so?
On 14.02.2024 09:46, David Brown wrote:
On 14/02/2024 00:44, Janis Papanagnou wrote:
And when was the first standard; 1998 - was it ISO/IEC 14882:1998
?
Yes.
Rather late. (I've had my professional C++ the decade before
that.)
I hadn't done much with C++ before then. At that time, most of my professional programming was in assembly (on small
microcontrollers) and Pascal, with only some C.
I'm surprised that Pascal was in professional use back then.[*]
Pascal had always been derided as "academic" or "toy" language.
On 14/02/2024 00:44, Janis Papanagnou wrote:
And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?
Yes.
Rather late. (I've had my professional C++ the decade before that.)
I hadn't done much with C++ before then. At that time, most of my professional programming was in assembly (on small microcontrollers) and Pascal, with only some C.
That's always the trouble with languages like C and C++. And backwards compatibility means that new, better features can't replace the old
features - you have to keep the old stuff too. (C++ is "braver" than C
at making breaking changes.)
On 14.02.2024 09:46, David Brown wrote:
On 14/02/2024 00:44, Janis Papanagnou wrote:
And when was the first standard; 1998 - was it ISO/IEC 14882:1998 ?
Yes.
Rather late. (I've had my professional C++ the decade before that.)
I hadn't done much with C++ before then. At that time, most of my
professional programming was in assembly (on small microcontrollers) and
Pascal, with only some C.
I'm surprised that Pascal was in professional use back then.[*]
Pascal had always been derided as "academic" or "toy" language.
On Tue, 13 Feb 2024 16:59:38 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Though personally, I'd probably make the assignment the operand of a
larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise
appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Agreed with two small exception:
(1) I never write '\0' myself always preferring plain 0.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
On 13.02.2024 17:34, David Brown wrote:
Though personally, I'd probably make the assignment the operand of a
larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise >appropriate to use directly as a condition).
On 14/02/2024 08:35, David Brown wrote:
On 13/02/2024 23:56, Malcolm McLean wrote:
On 13/02/2024 20:58, Keith Thompson wrote:
Responsible programmers aim for correctness, for everything they code,Now I know that you think Bart should just use make.
all the time. They don't aim to find their bugs in testing, they aim to
write code that they /know/ is correct, by design, and by knowledge of
the surrounding code, the language, the tools. Sometimes they make
mistakes. Sometimes there is an error outside their control, such as in
the specifications. Sometimes outside pressure - management, sales,
etc., - force them to leave code that they know is buggy or has high
risks of errors. But they are not happy about it, and they don't ignore
clear errors with "it will be fine".
But let's say it's
agreed to proceed with the system I proposed, which is a C interpeter to >drive a build script.
But C has a *lot* of precedence levels, and they're not all obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my head
...
Though most precedence rules in C make parenthesis usually unnecessary
and expressions rarely need parenthesis to provide that certainty.
scott@slp53.sl.home (Scott Lurndal) writes:
Michael S <already5chosen@yahoo.com> writes:
On Tue, 13 Feb 2024 16:59:38 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Though personally, I'd probably make the assignment the operand of a
larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise
appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Agreed with two small exception:
(1) I never write '\0' myself always preferring plain 0.
I'm in Keith's camp here when working with a char type, I'll
use '\0' rather than plain zero.
I tend to suffix constants as well if they're not being
used as 'int', perhaps a bit too picky?
uint64_t v;
...
if (v == 0ul) ...
There's no suffix for uint64_t. 0ul is of type unsigned long, which may
or may not be the same type as uint64_t.
In this particular case, I'd just use 0. If for some reason I needed to
make it explicitly of type uint64_t (say, for an argument to a variadic function), I'd write `(uint64_t)0`.
Do you know what "incompatible types" are, and what they mean? Do you realise that they cannot be swapped around as you suggest?
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my head
...
So don’t remember “off the top of your head”: keep the docs handy. That’s
what I do.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
scott@slp53.sl.home (Scott Lurndal) writes:
Michael S <already5chosen@yahoo.com> writes:
On Tue, 13 Feb 2024 16:59:38 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Though personally, I'd probably make the assignment the operand of a >>>>> larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise >>>>> appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Agreed with two small exception:
(1) I never write '\0' myself always preferring plain 0.
I'm in Keith's camp here when working with a char type, I'll
use '\0' rather than plain zero.
I tend to suffix constants as well if they're not being
used as 'int', perhaps a bit too picky?
uint64_t v;
...
if (v == 0ul) ...
There's no suffix for uint64_t. 0ul is of type unsigned long, which may
or may not be the same type as uint64_t.
In this particular case, I'd just use 0. If for some reason I needed to
make it explicitly of type uint64_t (say, for an argument to a variadic
function), I'd write `(uint64_t)0`.
stdint.h also provides an UINT64_C(...) macro that could be used,
though, as you say, 0 is really all that's needed in this case.
It's actually highly confusing for me as well.
For reasons I am not fully understand, it is interpreted as
a += (b += c)
which is obviously legal.
I don't understand why it isn't interpreted as
(a += b) += c
which is [a little less obviously] illegal.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
scott@slp53.sl.home (Scott Lurndal) writes:
Michael S <already5chosen@yahoo.com> writes:
On Tue, 13 Feb 2024 16:59:38 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Though personally, I'd probably make the assignment the operand of a >>>>> larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise >>>>> appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Agreed with two small exception:
(1) I never write '\0' myself always preferring plain 0.
I'm in Keith's camp here when working with a char type, I'll
use '\0' rather than plain zero.
I tend to suffix constants as well if they're not being
used as 'int', perhaps a bit too picky?
uint64_t v;
...
if (v == 0ul) ...
There's no suffix for uint64_t. 0ul is of type unsigned long,
which may or may not be the same type as uint64_t.
In this particular case, I'd just use 0. If for some reason I
needed to make it explicitly of type uint64_t (say, for an argument
to a variadic function), I'd write `(uint64_t)0`.
stdint.h also provides an UINT64_C(...) macro that could be used,
though, as you say, 0 is really all that's needed in this case.
Michael S <already5chosen@yahoo.com> writes:
On Tue, 13 Feb 2024 16:59:38 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Though personally, I'd probably make the assignment the operand of a
larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I personally
prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is otherwise
appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Agreed with two small exception:
(1) I never write '\0' myself always preferring plain 0.
I'm in Keith's camp here when working with a char type, I'll
use '\0' rather than plain zero.
I tend to suffix constants as well if they're not being
used as 'int', perhaps a bit too picky?
uint64_t v;
...
if (v == 0ul) ...
scott@slp53.sl.home (Scott Lurndal) writes:
Michael S <already5chosen@yahoo.com> writes:
On Tue, 13 Feb 2024 16:59:38 -0800
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Though personally, I'd probably make the assignment the operand
of a larger expression. I understand that
if (foo)
is a common idiom where foo is of any scalar type, but I
personally prefer to write one of
if (foo != 0)
if (foo != '\0')
if (foo != 0.0)
if (foo != NULL)
because I find it clearer (unless foo is of type bool or is
otherwise appropriate to use directly as a condition).
Thus if x and y are ints, I'd probably write:
if ((x = y) != 0)
(Assuming I'm not required to follow MISRA rules.)
YMMV.
Agreed with two small exception:
(1) I never write '\0' myself always preferring plain 0.
I'm in Keith's camp here when working with a char type, I'll
use '\0' rather than plain zero.
I tend to suffix constants as well if they're not being
used as 'int', perhaps a bit too picky?
uint64_t v;
...
if (v == 0ul) ...
There's no suffix for uint64_t. 0ul is of type unsigned long,
which may or may not be the same type as uint64_t.
In this particular case, I'd just use 0. If for some reason I
needed to make it explicitly of type uint64_t (say, for an
argument to a variadic function), I'd write `(uint64_t)0`.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all
obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my
head ...
So don't remember off the top of your head, [just] keep the docs
handy. That's what I do.
Why? The code is easier to read and maintain if the precedence is
made explicit.
On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:
Though most precedence rules in C make parenthesis usually unnecessary
and expressions rarely need parenthesis to provide that certainty.
And yet you were the one who added unnecessary ones in your example, I didn’t.
On 14/02/2024 11:43, Malcolm McLean wrote:
The whole point of using C s to get away from the ad hoc scripting
language that you don't use frequently enough to remember exactly how
it works, and to use something familiar. So we do want a C
interpreter, not a "C-like interpreter" to add yet another language
with its own quirks to the mess which Bart has so correctly identiifed.
Please stop using the "royal we" to mean you, personally. If there were
many people wanting C interpreters for writing scripts, there would be
lots of C interpreters and lots of scripts written in C. The reality is
that there is one dead project, and there's tcc's script mode - but I
have never heard of it being used in practice. Meanwhile, there are
vast numbers of C programmers, and vast amounts of scripts written in
Bash, Perl, Python, TCL, and other languages suitable for scripting.
That should be a good indication that few people feel the need for
writing scripts in C, even if they are familiar with C.
Early Unix did have some methods for accomodating
upper-case-only keyboards, some of which survive to the present.
address = (0xcul << 44) | ((uint64_t)node << 44) | (device << 32) | register_offset;
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
And yet, all the examples posted so far have involved, not the actual
types, but pointers to them.
Because pointers to incompatible types are a good way to demonstrate incompatibility.
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
In the DOS/Windows world, Pascal was a major language for a long time - starting with Turbo Pascal, then Borland Pascal for DOS then Windows,
then Delphi. Delphi's descendants are still in heavy use for Windows development. (And dotnet came from Delphi and related projects.)
It's worth to add Awk to your list of script languages, since it's
standard on Unix, and its syntax largely resembles the syntax of C.
You're suggesting that correctness doesn't matter unless the software controls nuclear missiles.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my
head ...
So don’t remember “off the top of your head”: keep the docs handy. >>That’s what I do.
Why? The code is easier to read and maintain if the precedence is made explicit.
On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:
On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:
Though most precedence rules in C make parenthesis usually unnecessary
and expressions rarely need parenthesis to provide that certainty.
And yet you were the one who added unnecessary ones in your example, I
didn’t.
Yes, and I explained that with the given rules you have no "clutter"
(as you called it) ...
On Mon, 12 Feb 2024 12:23:35 +0100, David Brown wrote:
Do you know what "incompatible types" are, and what they mean? Do you
realise that they cannot be swapped around as you suggest?
And yet, all the examples posted so far have involved, not the actual
types, but pointers to them.
On Wed, 14 Feb 2024 21:54:32 GMT, Scott Lurndal wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my
head ...
So don’t remember “off the top of your head”: keep the docs handy. >>> That’s what I do.
Why? The code is easier to read and maintain if the precedence is made
explicit.
You’re assuming that the parenthesis clutter has negligible effect on readability. That may be OK with one or two extraneous pairs, but typical
C code tends to end up with a lot more than that.
On Thu, 15 Feb 2024 08:00:00 +0100, Janis Papanagnou wrote:
On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:
On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:
Though most precedence rules in C make parenthesis usually unnecessary >>>> and expressions rarely need parenthesis to provide that certainty.
And yet you were the one who added unnecessary ones in your example, I
didn’t.
Yes, and I explained that with the given rules you have no "clutter"
(as you called it) ...
“Clutter” is when you put in ones you don’t need.
If Marie Kondo were to learn C programming, what do you think she would
do?
scott@slp53.sl.home (Scott Lurndal) writes:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all
obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my
head ...
So don't remember off the top of your head, [just] keep the docs
handy. That's what I do.
Why? The code is easier to read and maintain if the precedence is
made explicit.
Every serious C developer should know all the operator precedence relationships without having to look them up.
In cases where it is still felt necessary to indicate how different
operators parse with respect to one another, it's better to do that
using spacing than with parentheses, as for example
a | b^c
or
alpha | beta ^ gamma
OTOH, all the systems the code in question run typedef uint64_t to unsigned long, so the 'ul' suffix works correctly in all forseeable usages in this application. And it's less to type than casting. Granted it's not particularly meaningful in the 0ul case, but it's a habit that does
come in handy in expressions like
uint64_t address;
address = (0xcul << 44) | ((uint64_t)node << 44) | (device << 32) | register_offset;
Yes, a cast on the constant would work as well. And yes, a good compiler will warn if the suffix is missing from the first constant value.
On 15/02/2024 07:37, Tim Rentsch wrote:
scott@slp53.sl.home (Scott Lurndal) writes:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all
obvious.
If I see `a | b ^ c`, I'm not likely to remember off the top of my
head ...
So don't remember off the top of your head, [just] keep the docs
handy. That's what I do.
Why? The code is easier to read and maintain if the precedence is
made explicit.
Every serious C developer should know all the operator precedence
relationships without having to look them up.
<https://en.wikipedia.org/wiki/No_true_Scotsman>
/Serious/ developers write code that is as clear as they can. They know where references are for when they need them, but do not waste cognitive effort memorising things that are better expressed in a different way
(such as by using parentheses or breaking expressions into parts).
In cases where it is still felt necessary to indicate how different
operators parse with respect to one another, it's better to do that
using spacing than with parentheses, as for example
a | b^c
or
alpha | beta ^ gamma
No, that is the silliest thing to do. Don't write code that looks like
what you think it should mean - even if it happens to match the somewhat arbitrary choices of a language. Write code that does exactly what you mean, clearly and unequivocally, and requires the minimum of cognitive
effort on the part of the reader.
People make mistakes, even if they are "serious C developers". And if
you start using spaces to make it look like you are correct, neither you
nor others looking at the code will notice mistakes like :
alpha ^ beta | gamma
If you use parentheses for less common operator precedence cases, as
Keith suggests, your code will be clear and there will be an obvious and immediate match between what the programmer intended, what the compiler
does, and what any reader (experienced or not) will see.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Michael S <already5chosen@yahoo.com> writes:
[...]
Here is another way to think about it.
C (and many or most other languages) are fairly strict about what
is allowed on the left-hand side of an assignment. For example,
a + b += c;
is not allowed. Neither is
(a + b) += c;
although the reasoning is a little different in the two cases,
neither is allowed, because neither one makes sense.
By analogy with the second example, the statement
(a += b) += c;
isn't allowed, because the left-hand side is wrong. So if we
see
a += b += c;
it would be silly to parse it as
(a += b) += c;
because that's illegal. The only other way to parse it, viz.,
a += (b += c);
passes the semantic prerequisites. Since it's the only way that
makes sense, it seems natural that (without any parentheses) the
syntax should reflect that.
I don't think that reasoning is entirely solid.
On 12.02.2024 02:17, Lawrence D'Oliveiro wrote:
You seem to be saying that something like
bool a = b == c;
should not be allowed.
I have the habit to write such specific expressions with parenthesis
a = (b == c);
for own convenience or better maintainability. (Just BTW.)
On Wed, 14 Feb 2024 15:29:00 +0100, David Brown wrote:
The UCSD p-system pioneered the concept of “write once, run anywhere”, by >defining a standardized p-code interpreter that could be implemented
across a whole range of different processor architectures. Once you had
done that, plus some basic OS routines, the main part of the software, >written in Pascal, should port straight across.
On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
The first version of the C++ standard was C++98, and that had bool in it.
On Wed, 14 Feb 2024 14:38:01 -0800, Keith Thompson wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
And yet, all the examples posted so far have involved, not the actual
types, but pointers to them.
Because pointers to incompatible types are a good way to demonstrate
incompatibility.
But it was those types I was talking about, not pointers to them.
On 15/02/2024 08:59, Lawrence D'Oliveiro wrote:
On Wed, 14 Feb 2024 21:54:32 GMT, Scott Lurndal wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Tue, 13 Feb 2024 14:19:20 -0800, Keith Thompson wrote:
But C has a *lot* of precedence levels, and they're not all obvious. >>>>>
If I see `a | b ^ c`, I'm not likely to remember off the top of my
head ...
So don’t remember “off the top of your head”: keep the docs handy. >>>> That’s what I do.
Why? The code is easier to read and maintain if the precedence is made
explicit.
You’re assuming that the parenthesis clutter has negligible effect on
readability. That may be OK with one or two extraneous pairs, but typical
C code tends to end up with a lot more than that.
That is an issue. It's hard to match parentheses in long expressions.
On Thu, 15 Feb 2024 08:23:09 +0100, Janis Papanagnou wrote:
It's worth to add Awk to your list of script languages, since it's
standard on Unix, and its syntax largely resembles the syntax of C.
Perl does everything Awk can do, and do it just as concisely
, and it can
do more besides.
On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:
You're suggesting that correctness doesn't matter unless the software
controls nuclear missiles.
I would be hoping that safety-critical software would be written to higher standards than military stuff.
After all, in military operations, a “friendly fire” rate of, say, 10-25%,
seems to be considered acceptable.
On 2024-02-15, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:
You're suggesting that correctness doesn't matter unless the software
controls nuclear missiles.
I would be hoping that safety-critical software would be written to higher >> standards than military stuff.
After all, in military operations, a “friendly fire” rate of, say, 10-25%,
seems to be considered acceptable.
Using garbage collection in a missile should be entirely acceptable; use
it liberally in development, and then in deployment, have enough RAM
and tune the parameters so that it strikes the target before the first
GC cycle.
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
The first version of the C++ standard was C++98, and that had bool in
it.
The first version of C++ was in the mid-80s and didn't have bool (c.f. cfront).
On 12.02.2024 02:13, Lawrence D'Oliveiro wrote:
But boolean is a subtype of int anyway, so what’s the harm in
redefining conditional expressions to return bool instead?
Well, no harm, but some useful constructs would probably not work any
more.
Just this morning I wrote[*], for example,
size = (size+1+shift)%3; // cycle through three sizes
where 'shift' is actually a boolean (with possible values 0 and 1).
[*] Actually in Javascript, but the expression is also valid in C.
I can't remember the precedence relationships beyond a few very
conventional and well known ones.
That is an issue. It's hard to match parentheses in long expressions.
On 15/02/2024 10:00, Lawrence D'Oliveiro wrote:
If Marie Kondo were to learn C programming, what do you think she would
do?
So now ...
On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:
That is an issue. It's hard to match parentheses in long expressions.
I have a simple answer to that: take advantage of the two dimensions of
space available to you on the screen/page:
if
(
nrhistentries <= 4
||
nrpixels
/
(
nrpixels
-
(
histogram[0].count
+
histogram[1].count
+
histogram[2].count
+
histogram[3].count
)
) /* won't be zero */
>=
count_factor
)
{
...
} /*if*/
= (/ nrpixels(- nrpixels
On Thu, 15 Feb 2024 08:23:09 +0100, Janis Papanagnou wrote:
It's worth to add Awk to your list of script languages, since it's
standard on Unix, and its syntax largely resembles the syntax of C.
Perl does everything Awk can do, and do it just as concisely, and it can
do more besides.
On Thu, 15 Feb 2024 08:00:00 +0100, Janis Papanagnou wrote:
On 14.02.2024 21:52, Lawrence D'Oliveiro wrote:
On Wed, 14 Feb 2024 00:18:50 +0100, Janis Papanagnou wrote:
Though most precedence rules in C make parenthesis usually unnecessary >>>> and expressions rarely need parenthesis to provide that certainty.
And yet you were the one who added unnecessary ones in your example, I
didn’t.
Yes, and I explained that with the given rules you have no "clutter"
(as you called it) ...
“Clutter” is when you put in ones you don’t need.
On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
The first version of the C++ standard was C++98, and that had bool in it.
And that is valid in JavaScript. Just tried it:
>> 2 + 2
4
>> 2 + true
3
>> 2 + false
2
On 2024-02-15, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Tue, 13 Feb 2024 12:58:49 -0800, Keith Thompson wrote:
You're suggesting that correctness doesn't matter unless the software
controls nuclear missiles.
I would be hoping that safety-critical software would be written to higher >> standards than military stuff.
After all, in military operations, a “friendly fire” rate of, say, 10-25%,
seems to be considered acceptable.
Using garbage collection in a missile should be entirely acceptable; use
it liberally in development, and then in deployment, have enough RAM
and tune the parameters so that it strikes the target before the first
GC cycle.
You can master Awk in few hours, not so Perl.
On Thu, 15 Feb 2024 16:41:23 +0000, Malcolm McLean wrote:
I can't remember the precedence relationships beyond a few very
conventional and well known ones.
No need to. This is why we have documentation. Keep it handy, and don’t be ashamed to refer to it often, even in the presence of colleagues.
On 2024-02-16, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:
That is an issue. It's hard to match parentheses in long expressions.
I have a simple answer to that: take advantage of the two dimensions of
space available to you on the screen/page:
if
(
nrhistentries <= 4
||
nrpixels
/
(
nrpixels
-
(
histogram[0].count
+
histogram[1].count
+
histogram[2].count
+
histogram[3].count
)
) /* won't be zero */
>=
count_factor
)
{
...
} /*if*/
At that point you start losing to Lisp. E.g. TXR Lisp:
On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
The first version of the C++ standard was C++98, and that had bool in it.
Yes. But my comment about the other poster being mistaken was where
he wrote about the time "When C++ was forked from C" (and not "When
C++ became standardized").
And then he squirmed by introducing vague terms to muddy this fault ("Pre-history vs history.")
The "fork from C" was (as BJ's book) in the 1980's, the standard in
the late 1990's.
And the other poster makes (obviously) a wrong claim about it being
in the first edition of Stroustrup's book.
(Is spreading "alternative facts" so established meanwhile?)
Janis
On Thu, 15 Feb 2024 16:47:12 +0000, Malcolm McLean wrote:
That is an issue. It's hard to match parentheses in long expressions.
I have a simple answer to that: take advantage of the two dimensions of
space available to you on the screen/page:
if
(
nrhistentries <= 4
||
nrpixels
/
(
nrpixels
-
(
histogram[0].count
+
histogram[1].count
+
histogram[2].count
+
histogram[3].count
)
) /* won't be zero */
>=
count_factor
)
{
...
} /*if*/
On 16/02/2024 04:03, Janis Papanagnou wrote:
On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:
You are mistaken; C++ had no 'bool' type initially. It had been
added later.
The first version of the C++ standard was C++98, and that had bool
in it.
Yes. But my comment about the other poster being mistaken was where
he wrote about the time "When C++ was forked from C" (and not "When
C++ became standardized").
That was me. I was wrong, and you corrected me. Thanks for that.
And then he squirmed by introducing vague terms to muddy this fault ("Pre-history vs history.")
I don't know to whom you are referring here, as I haven't seen any
posts like that. I certainly didn't make any. (Are you making up
your own "alternative facts" here?)
I did say that the C++ standards committee felt more able to make
breaking changes to the language when they standardised it, which is
not "squirming" - it is fact. In particular, when they introduced
"bool" they changed the definition of relational operators to
evaluate to a "bool" result rather than an "int" result. The C
standards committee did not make a similar change when they
introduced _Bool in C99.
The "fork from C" was (as BJ's book) in the 1980's, the standard in
the late 1990's.
Yes.
The first C++ ISO standard was 1998. Prior to that, it had a couple
of editions of "The C++ Programming Language" (I think I have the
second edition on my shelf), then the "C++ Annotated Reference
Manual" which was a "de-facto standard" on the lines of "K&R C".
It seems "bool" didn't make it until C++98, which surprised me.
And the other poster makes (obviously) a wrong claim about it being
in the first edition of Stroustrup's book.
(Is spreading "alternative facts" so established meanwhile?)
Janis
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
[...] It's hard to match parentheses in long expressions.
Not if you're using an editor like vim, which highlights the
matching paranthesis/brace/bracket automatically, if configured to
do so.
scott@slp53.sl.home (Scott Lurndal) writes:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
[...] It's hard to match parentheses in long expressions.
Not if you're using an editor like vim, which highlights the
matching paranthesis/brace/bracket automatically, if configured to
do so.
There are several problem with that:
On 16/02/2024 20:20, Chris M. Thomasson wrote:
On 2/15/2024 5:16 PM, Lawrence D'Oliveiro wrote:
On Thu, 15 Feb 2024 16:41:23 +0000, Malcolm McLean wrote:
I can't remember the precedence relationships beyond a few very
conventional and well known ones.
No need to. This is why we have documentation. Keep it handy, and
don’t be
ashamed to refer to it often, even in the presence of colleagues.
Agreed. In fact, double checking something in front of colleagues
might make them feel better, so to speak. Too ashamed to double check
something can lead to errors, bug, oh my! :^)
Usually it's pretty clear what the expression should say, so whip
parentheses in. Rerun. If behaviour changes, that was your bug. If not,
at least you've made it clearer. But you never actually find out what
the precedence relations are.
No, that's not Linux-centric at all!
You don't see it because you permanently live in a Unix-shaped box and everything you deal with is designed for that box.
I see no benefit in a "C" interpreter - for which string handling is an afterthought - in any build process.
And use good tools, such as an IDE that gives you suggestions and auto-completion.
Just use parentheses; Your precedence-fu may fail tomorrow.
hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
// ...
}
Here's a clue. It's one thing to mark your #endif's with a comment on
which #ifdef it matches, but if you need to do that with your "if" statements, your style is an incomprehensible mess.
On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:
hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
// ...
}
I see you had to shorten the variable names as well. Descriptive layout
*and* names too much for you?
On Tue, 13 Feb 2024 22:50:40 +0000, bart wrote:
You don't see it because you permanently live in a Unix-shaped box and
everything you deal with is designed for that box.
Think of the walls of any box as dividing the Universe into two parts. The way you tell which is which is that “inside” is normally much smaller than
“outside”.
Now think of the wall between you and us: we are the ones who are free to stretch our arms out, walk and run and even fly about freely, while you
are the one complaining about not being able to do the same.
Which one sounds more like “inside” and which one “outside”?
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
Usually it's pretty clear what the expression should say, so whip
parentheses in. Rerun. If behaviour changes, that was your bug. If
not, at least you've made it clearer. But you never actually find out
what the precedence relations are.
Is that a joke?
Would you seriously add parentheses to an expression and re-run to see
if the behavior changes *without bothering to look up the actual
precedence rules*?
Is that a joke?
Would you seriously add parentheses to an expression and re-run to see
if the behavior changes *without bothering to look up the actual
precedence rules*?
On 2024-02-17, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
Usually it's pretty clear what the expression should say, so whip
parentheses in. Rerun. If behaviour changes, that was your bug. If
not, at least you've made it clearer. But you never actually find out
what the precedence relations are.
Is that a joke?
Would you seriously add parentheses to an expression and re-run to see
if the behavior changes *without bothering to look up the actual
precedence rules*?
It seems it might be mildly useful to have (? ...) parentheses which
override precedence and associativily like the regular ones, but emit a diagnostic.
If the parentheses are necessary, the diagnostic indicates that.
If the parentheses do nothing, it also indicates that.
So based on the diagnostic, you remove just the ? or the entire
(? ...).
In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
...
Is that a joke?
Would you seriously add parentheses to an expression and re-run to see
if the behavior changes *without bothering to look up the actual
precedence rules*?
Most people (i.e., sane people) don't take a copy of the latest C standards docs with them on vacation.
Nor do they take them on dates. Or most other places.
On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:
Here's a clue. It's one thing to mark your #endif's with a comment on
which #ifdef it matches, but if you need to do that with your "if"
statements, your style is an incomprehensible mess.
I wonder why ...
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
And use good tools, such as an IDE that gives you suggestions and
auto-completion.
auto-completion doesn’t really take you far, though. My favourite example >> is how many times people write “sqrt(x * x + y * y)” to compute a
hypotenuse, not realizing that there is a “hypot(x, y)” function available
in any reasonable maths library.
More relevantly, it's in the C standard library (since C99, I think).
On 17/02/2024 11:04, David Brown wrote:
On 17/02/2024 02:13, Keith Thompson wrote:And in graphics software, taking the square root to normalise a vector
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
And use good tools, such as an IDE that gives you suggestions and
auto-completion.
auto-completion doesn’t really take you far, though. My favourite
example
is how many times people write “sqrt(x * x + y * y)” to compute a
hypotenuse, not realizing that there is a “hypot(x, y)” function
available
in any reasonable maths library.
More relevantly, it's in the C standard library (since C99, I think).
Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
virtually any real system.
"hypot" is generally not implemented as a dedicated hardware
instruction, and is thus handled in software - it will involve a
library call to a "hypot" function that finds the maximum absolute
values of x and y, divides both x and y by this, then squares them and
adds them, then finds the square root, and then multiplies up again -
all so that it will give the correct result without a risk of overflow.
And that's great, if your x and y are nearing half the maximum range
of your floating point type. But how often is that realistic?
The "sqrt(x * x + y * y)" version will generally be inlined with two
multiples, an add, and a square root function - much faster,
especially if the compiler can vectorize the code or interleave it
with other instructions.
A very quick test on my machine had the sqrt() version running at
least 3 times the speed of the hypot() version.
Of course speed is not everything, and if you need the range
guarantees of hypot(), you need them - but it would be silly to
suggest that "hypot" is always better.
is often the single most expensive step.
On 17/02/2024 06:07, Kenny McCormack wrote:
In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
...
Is that a joke?
Would you seriously add parentheses to an expression and re-run to see
if the behavior changes *without bothering to look up the actual
precedence rules*?
Most people (i.e., sane people) don't take a copy of the latest C standards >> docs with them on vacation.
Nor do they take them on dates. Or most other places.
<https://letmegooglethat.com/?q=c+operator+precedence>
Most people have their phone with them on vacation.
David Brown <david.brown@hesbynett.no> writes:
On 17/02/2024 06:07, Kenny McCormack wrote:
In article <8734tr9ajg.fsf@nosuchdomain.example.com>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
...
Is that a joke?
Would you seriously add parentheses to an expression and re-run to see >>>> if the behavior changes *without bothering to look up the actual
precedence rules*?
Most people (i.e., sane people) don't take a copy of the latest C standards >>> docs with them on vacation.
Nor do they take them on dates. Or most other places.
<https://letmegooglethat.com/?q=c+operator+precedence>
Most people have their phone with them on vacation.
Even if they do, they may not have a data plan.
On 16/02/2024 04:03, Janis Papanagnou wrote:
On 15.02.2024 09:48, Lawrence D'Oliveiro wrote:
On Tue, 13 Feb 2024 16:55:32 +0100, Janis Papanagnou wrote:
You are mistaken; C++ had no 'bool' type initially. It had been added
later.
The first version of the C++ standard was C++98, and that had bool in
it.
Yes. But my comment about the other poster being mistaken was where
he wrote about the time "When C++ was forked from C" (and not "When
C++ became standardized").
That was me. I was wrong, and you corrected me. Thanks for that.
And then he squirmed by introducing vague terms to muddy this fault
("Pre-history vs history.")
I don't know to whom you are referring here, as I haven't seen any posts
like that. I certainly didn't make any. (Are you making up your own "alternative facts" here?)
[...]
OK, let's everyone who takes a computer with them planning on doing >programming is likely to have the ability to look things up online. We
are no longer in the 1990's.
On 15/02/2024 13:20, David Brown wrote:
[...]
You have to wonder why the creators of C thought it was a good idea in
the first place to have so many precedence levels, if you're going to
end up using parentheses anyway to disambiguate.
There are 10 levels for binary operators (excl. augmented assignment);
for the same set of operators, I have only 5 for example.
I don't know about other languages, but splitting == != < <= >= > into
two levels is surely an odd thing to do, for a start.
On Sat, 17 Feb 2024 12:04:28 +0100
David Brown <david.brown@hesbynett.no> wrote:
On 17/02/2024 02:13, Keith Thompson wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes: =20=20
On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote: =20=20
And use good tools, such as an IDE that gives you suggestions and
auto-completion. =20
auto-completion doesn=E2=80=99t really take you far, though. My favour= >ite
example is how many times people write =E2=80=9Csqrt(x * x + y * y)=E2= >=80=9D to
compute a hypotenuse, not realizing that there is a =E2=80=9Chypot(x, = >y)=E2=80=9D
function available in any reasonable maths library. =20
More relevantly, it's in the C standard library (since C99, I
think).=20
Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on=20
virtually any real system.
=20
"hypot" is generally not implemented as a dedicated hardware=20
instruction, and is thus handled in software - it will involve a
library call to a "hypot" function that finds the maximum absolute
values of x and y, divides both x and y by this, then squares them
and adds them, then finds the square root, and then multiplies up
again - all so that it will give the correct result without a risk of
overflow.
It is not how it is done and *not* because division is slow, but
because your method could produce the result that is off by one LS bit.
Most likely, a library implementation looks like that, at least >algorithmically:
double hypot(double x, double y)
On 17/02/2024 02:13, Keith Thompson wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
And use good tools, such as an IDE that gives you suggestions and
auto-completion.
auto-completion doesn’t really take you far, though. My favourite
example is how many times people write “sqrt(x * x + y * y)” to
compute a hypotenuse, not realizing that there is a “hypot(x, y)”
function available in any reasonable maths library.
More relevantly, it's in the C standard library (since C99, I
think).
Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
virtually any real system.
"hypot" is generally not implemented as a dedicated hardware
instruction, and is thus handled in software - it will involve a
library call to a "hypot" function that finds the maximum absolute
values of x and y, divides both x and y by this, then squares them
and adds them, then finds the square root, and then multiplies up
again - all so that it will give the correct result without a risk of overflow.
And that's great, if your x and y are nearing half the maximum range
of your floating point type. But how often is that realistic?
The "sqrt(x * x + y * y)" version will generally be inlined with two multiples, an add, and a square root function - much faster,
especially if the compiler can vectorize the code or interleave it
with other instructions.
A very quick test on my machine had the sqrt() version running at
least 3 times the speed of the hypot() version.
Of course speed is not everything, and if you need the range
guarantees of hypot(), you need them - but it would be silly to
suggest that "hypot" is always better.
Michael S <already5chosen@yahoo.com> writes:
On Sat, 17 Feb 2024 12:04:28 +0100
David Brown <david.brown@hesbynett.no> wrote:
On 17/02/2024 02:13, Keith Thompson wrote:ite
Lawrence D'Oliveiro <ldo@nz.invalid> writes: =20
On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote: =20
And use good tools, such as an IDE that gives you suggestions
and auto-completion. =20
auto-completion doesn=E2=80=99t really take you far, though. My
favour=
=80=9D toexample is how many times people write =E2=80=9Csqrt(x * x + y
* y)=E2=
y)=E2=80=9Dcompute a hypotenuse, not realizing that there is a
=E2=80=9Chypot(x, =
=20function available in any reasonable maths library. =20=20
More relevantly, it's in the C standard library (since C99, I
think).=20
Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on=20
virtually any real system.
=20
"hypot" is generally not implemented as a dedicated hardware=20
instruction, and is thus handled in software - it will involve a
library call to a "hypot" function that finds the maximum absolute
values of x and y, divides both x and y by this, then squares them
and adds them, then finds the square root, and then multiplies up
again - all so that it will give the correct result without a risk
of overflow.
It is not how it is done and *not* because division is slow, but
because your method could produce the result that is off by one LS
bit. Most likely, a library implementation looks like that, at least >algorithmically:
double hypot(double x, double y)
Or perhaps like this:
https://github.com/lattera/glibc/blob/master/sysdeps/ieee754/dbl-64/e_hypot.c
Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
virtually any real system.
"hypot" is generally not implemented as a dedicated hardware
instruction, and is thus handled in software - it will involve a
library call to a "hypot" function that finds the maximum absolute
values of x and y, divides both x and y by this, then squares them and
adds them, then finds the square root, and then multiplies up again -
all so that it will give the correct result without a risk of overflow.
And that's great, if your x and y are nearing half the maximum range
of your floating point type. But how often is that realistic?
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
scott@slp53.sl.home (Scott Lurndal) writes:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
[...] It's hard to match parentheses in long expressions.
Not if you're using an editor like vim, which highlights the
matching paranthesis/brace/bracket automatically, if configured to
do so.
There are several problem with that:
No, there are not. It works as described _when using and editor
like vim_.
Cases where you're not using 'vim' are irrelevent to that
statement, even if otherwise on point.
I'd point out that the last time I read code without using an
editor such as vi/vim were line printer printouts in the 80's.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
In this particular case, I'd just use 0. If for some reason I
needed to make it explicitly of type uint64_t (say, for an
argument to a variadic function), I'd write `(uint64_t)0`.
Ick. At least write '(uint64_t){ 0 }' rather than casting.
Why?
[...] But anyone who knows C can recognize
that casting a constant 0 to an integer type is not in any way
dangerous.
Okay, that seems to be what I was also saying. (I don't know the terms Bodmas/Bidmas, though. Here we have the "Punkt vor Strich" Rule; "dot
before dash", where the dot operations are mult and add, and the dash
operations plus and minus, according to the symbols used in writing,
'·' ':' '+' '-'.)
In computer programs it is normally acceptable to write a = b + c * d
and because programs contain so many similar expressions, and because
the reader is another programmer and knows that the meaning is
constrained by the language as well as by convention, it will not cause
any confusion. But in a non-computer, non-professional mathematical
context, it is too likely to cause confusion, and you must write a = b +
(c * d).
That's for the widely known and accepted convention about the four rules
of arithmetic. Taught in British schools as Bodmas, or sometimes Bidmas
(i is for index).
Enough people also know that "or" is lower precedence
than "and" in logical expressions. But for anything else, all bets are
off, and again, you must use parentheses.
On 16/02/2024 22:45, Lawrence D'Oliveiro wrote:
Which one sounds more like “inside” and which one “outside”?
It sounds like you're the ones who are locked in to all those myriad different tools and all your different systems.
Yes, casts certainly can be dangerous ...
I recall that we had used the _specific literal constant_ 0 as a
"universal" constant to all integral types, floats, and pointers without cast.[*] That was in the 1990's.
And that's great, if your x and y are nearing half the maximum range of
your floating point type. But how often is that realistic?
On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:
On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:
hsum = hist[0].count+hist[1].count+hist[2].count+hist[3].count;
if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
// ...
}
I see you had to shorten the variable names as well. Descriptive layout
*and* names too much for you?
Keep local variable names short and snappy is part of knowing how to
write readable code.
(I don't know the terms Bodmas/Bidmas, though. ...
On 17/02/2024 00:11, Lawrence D'Oliveiro wrote:
On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:
Here's a clue. It's one thing to mark your #endif's with a comment on
which #ifdef it matches, but if you need to do that with your "if"
statements, your style is an incomprehensible mess.
I wonder why ...
/You/ wrote it, and I've not seen anyone but you post code with " }
/*if*/ " comments. So only you can explain why your feel your own style
is such an incomprehensible mess.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
On 18.02.2024 01:45, Keith Thompson wrote:
[...] But anyone who knows C can recognize
that casting a constant 0 to an integer type is not in any way
dangerous.
That's what I'd expect. Moreover...
I recall that we had used the _specific literal constant_ 0 as a
"universal" constant to all integral types, floats, and pointers
without cast.[*] That was in the 1990's. Are there meanwhile any
restrictions on using 0 without cast?
0 is of type int. In most contexts, it will be implicitly converted to
any scalar type -- which is why { 0 } is a valid initializer for any
type (C23 will allow {}).
The problem is contexts where that conversion
doesn't occur. The most common is an argument to a variadic function;
for example printf("%ld\n", 0) has undefined behavior.
A less common
case is a call to a function with an old-style non-prototype
declaration.
[*] I anyway preferred '\0', 0.0, or a 'null' constant definition
for pointers.
I presume you mean NULL (and C23 adds nullptr).
But note that NULL
requires a cast in some cases, like printf("%p\n", (void*)NULL);
This is exactly what I was remembering.
On Sun, 18 Feb 2024 02:35:37 +0100, Janis Papanagnou wrote:
I recall that we had used the _specific literal constant_ 0 as a
"universal" constant to all integral types, floats, and pointers without
cast.[*] That was in the 1990's.
That is still true in the C spec today. Note that “0” as a pointer does not mean that the address value has to be zero: the implementation is expected to convert the integer literal 0 to whatever address value is
meant to be interpreted as “no such address”.
On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:
Yes, casts certainly can be dangerous ...
This is why C++ defined four different kinds of casting. The
dangerous one is called “reinterpret_cast”, while the others are much safer to use.
On Fri, 16 Feb 2024 23:44:10 +0000, bart wrote:
On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:
On Fri, 16 Feb 2024 10:01:37 +0000, bart wrote:
hsum =
hist[0].count+hist[1].count+hist[2].count+hist[3].count;
if(nrhist<=4 || nrpixels / (nrpixels - hsum) >= count_factor ) {
// ... }
I see you had to shorten the variable names as well. Descriptive
layout *and* names too much for you?
Keep local variable names short and snappy is part of knowing how to
write readable code.
That’s about making the code easier to write, not easier to read.
Don’t confuse the two. And don’t assume that the first has more importance than the second.
On 18/02/2024 01:22, Keith Thompson wrote:
What audience are you writing for that knows that "*" meansAnyone who either thinks that the rule to to apply the operations in
multiplication but won't understand "a = b + c * d;"?
[...]
sequence from left to right, or thinks that the writer may be using this rule, or who thinks that if you enter the expression into a calculator,
the calculator is always right.
On 18/02/2024 01:22, Keith Thompson wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:Anyone who either thinks that the rule to to apply the operations in
[...]
In computer programs it is normally acceptable to write a = b + c * d
and because programs contain so many similar expressions, and because
the reader is another programmer and knows that the meaning is
constrained by the language as well as by convention, it will not
cause any confusion. But in a non-computer, non-professional
mathematical context, it is too likely to cause confusion, and you
must write a = b + (c * d).
What audience are you writing for that knows that "*" means
multiplication but won't understand "a = b + c * d;"?
[...]
sequence from left to right, or thinks that the writer may be using this rule, or who thinks that if you enter the expression into a calculator,
the calculator is always right.
On 17/02/2024 01:43, Kaz Kylheku wrote:
It seems it might be mildly useful to have (? ...) parentheses
which override precedence and associativily like the regular ones,
but emit a diagnostic.
If the parentheses are necessary, the diagnostic indicates that.
If the parentheses do nothing, it also indicates that.
So based on the diagnostic, you remove just the ? or the entire
(? ...).
Okay, but they help with semantics, so just leave them in. Is it
better to remove them and add a commnent ... ? // didn't expect
that!
Do extra parens in the source - when they turn out to be
unnecessary - result in bloated executable size?
Or will the compiler optimise them away?
Do extra parens in the source help the human reader?
On 18/02/2024 11:30, bart wrote:
On 18/02/2024 07:48, Malcolm McLean wrote:
On 18/02/2024 01:22, Keith Thompson wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:Anyone who either thinks that the rule to to apply the operations in
[...]
In computer programs it is normally acceptable to write a = b + c * d >>>>> and because programs contain so many similar expressions, and because >>>>> the reader is another programmer and knows that the meaning is
constrained by the language as well as by convention, it will not
cause any confusion. But in a non-computer, non-professional
mathematical context, it is too likely to cause confusion, and you
must write a = b + (c * d).
What audience are you writing for that knows that "*" means
multiplication but won't understand "a = b + c * d;"?
[...]
sequence from left to right, or thinks that the writer may be using
this rule, or who thinks that if you enter the expression into a
calculator, the calculator is always right.
1970s calculators might have been too crude to use precedence. But
Casio calculator now will give you 14 if you enter '2 + 3 x 4'. Any
calculator app will do so. Even Google will give you 14 if you enter
that.
Very few expect it to be 20.
Oh you are right. I pushed it into the calculator that ships with my
Mac, and it is 14. It did use to be 20 for that type of calculator.
The one I had at school would have answered 20. But I seldom used
calculators after leaving school. They can't do the sums you have to do
at university.
On Sun, 18 Feb 2024 06:46:36 +0100, Janis Papanagnou wrote:
This is exactly what I was remembering.
This is why it helps to keep a copy of the docs handy.
On 18/02/2024 02:28, Lawrence D'Oliveiro wrote:
On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:
Yes, casts certainly can be dangerous ...
This is why C++ defined four different kinds of casting.
The dangerous one
is called “reinterpret_cast”, while the others are much safer to use.
And my experience is the opposite. Reinterpeting a bit pattern as
something else is a safe and proper use of a cast, whilst calling user-defined code without necessarily realising it is dangerous, and manipulating inheritance hierachies in strange ways is also confusing
and dangerous.
On Sun, 18 Feb 2024 02:28:33 -0000 (UTC)
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
On Sat, 17 Feb 2024 16:45:49 -0800, Keith Thompson wrote:
Yes, casts certainly can be dangerous ...
This is why C++ defined four different kinds of casting. The
dangerous one is called “reinterpret_cast”, while the others are much
safer to use.
Potential usefulness of the distinction almost fully nullified both
by retention of C-style cast and by presence of similarly omnipotent function-style cast that C++ added on its own.
On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:
(I don't know the terms Bodmas/Bidmas, though. ...
We learned BODMAS, too. Although I remember the “O” stood for “Of”, as in
implied multiplication. So that binds more tightly than division (“D”), which in turn binds more tightly than explicit multiplication (“M”). So for example
a ÷ b(c + d)
should be interpreted as
a ÷ (b(c + d))
while
a ÷ b × (c + d)
should be interpreted as
(a ÷ b) × (c + d)
On Sat, 17 Feb 2024 12:04:28 +0100
David Brown <david.brown@hesbynett.no> wrote:
On 17/02/2024 02:13, Keith Thompson wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Fri, 16 Feb 2024 08:54:21 +0100, David Brown wrote:
And use good tools, such as an IDE that gives you suggestions and
auto-completion.
auto-completion doesn’t really take you far, though. My favourite
example is how many times people write “sqrt(x * x + y * y)” to
compute a hypotenuse, not realizing that there is a “hypot(x, y)”
function available in any reasonable maths library.
More relevantly, it's in the C standard library (since C99, I
think).
Also relevant, IMHO, is that "sqrt(x * x + y * y)" is faster on
virtually any real system.
"hypot" is generally not implemented as a dedicated hardware
instruction, and is thus handled in software - it will involve a
library call to a "hypot" function that finds the maximum absolute
values of x and y, divides both x and y by this, then squares them
and adds them, then finds the square root, and then multiplies up
again - all so that it will give the correct result without a risk of
overflow.
It is not how it is done and *not* because division is slow, but
because your method could produce the result that is off by one LS bit.
Most likely, a library implementation looks like that, at least algorithmically:
On Sat, 17 Feb 2024 12:04:28 +0100, David Brown wrote:
And that's great, if your x and y are nearing half the maximum range of
your floating point type. But how often is that realistic?
There is an old saying: “correctness comes before efficiency”.
A key principle of IEEE754 is that users, particularly users nonexpert in
the field of numerics, should be exposed to a minimum of surprise.
"i" is effectively a keyword, and "i=0" was picked up as one of the most common sequences in C by some sort of analysis. I think it was for compression. Just out "int i;" at the top and you have it in scope and
handy.
And don't decare it in the loop because you can't then do
for (i = 0; i < N; i++)
if(!x[i])
break;
if (i == N)
and you don't want a mix of counter variables declared in the loop and variables not. It's not a huge deal. But it is that bit harder to
understand and to read.
On 18/02/2024 01:22, Keith Thompson wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:Anyone who either thinks that the rule to to apply the operations in
[...]
In computer programs it is normally acceptable to write a = b + c * d
and because programs contain so many similar expressions, and because
the reader is another programmer and knows that the meaning is
constrained by the language as well as by convention, it will not
cause any confusion. But in a non-computer, non-professional
mathematical context, it is too likely to cause confusion, and you
must write a = b + (c * d).
What audience are you writing for that knows that "*" means
multiplication but won't understand "a = b + c * d;"?
sequence from left to right, or thinks that the writer may be using this rule, or who thinks that if you enter the expression into a calculator,
the calculator is always right.
On Sat, 17 Feb 2024 12:11:36 +0100, David Brown wrote:
On 17/02/2024 00:11, Lawrence D'Oliveiro wrote:
On Fri, 16 Feb 2024 08:59:35 +0100, David Brown wrote:
Here's a clue. It's one thing to mark your #endif's with a comment on >>>> which #ifdef it matches, but if you need to do that with your "if"
statements, your style is an incomprehensible mess.
I wonder why ...
/You/ wrote it, and I've not seen anyone but you post code with " }
/*if*/ " comments. So only you can explain why your feel your own style
is such an incomprehensible mess.
You are the one who has never seen it before, and so you react with
ignorance and fear. Almost as though the code has become like magic to
you.
You are the one calling it an “incomprehensible mess”, it is up to you to back up your claim.
[...] Different countries have
different rules, and the rules change over time.
In article <uqqrd3$h6ku$1@dont-email.me>,
David Brown <david.brown@hesbynett.no> wrote:
...
OK, let's everyone who takes a computer with them planning on doing
programming is likely to have the ability to look things up online. We
are no longer in the 1990's.
From which language was the above paragraph Google-translated?
On 18.02.2024 13:09, Malcolm McLean wrote:
"i" is effectively a keyword, and "i=0" was picked up as one of the
most common sequences in C by some sort of analysis. I think it was
for compression. Just out "int i;" at the top and you have it in
scope and handy.
Sure.
And don't decare it in the loop because you can't then do
for (i = 0; i < N; i++)
if(!x[i])
break;
if (i == N)
and you don't want a mix of counter variables declared in the loop
and variables not. It's not a huge deal. But it is that bit harder
to understand and to read.
You could of course use a semantical name and keep variables localized
bool null_found = false;
for (int i = 0; i < N; i++)
if(!x[i]) {
null_found = true; break;
}
if (! null_found)
(Of course you should find a better, more sensible name for the !x[i] condition, which I cannot guess from the few lines above.)
But that's of course a style issue, where opinions certainly differ,
and that people who prefer terse names and terse code will probably
dislike this. (Myself I like local declarations and semantical names.)
Janis
On 18.02.2024 03:07, Keith Thompson wrote:...
0 is of type int. In most contexts, it will be implicitly converted to
any scalar type -- which is why { 0 } is a valid initializer for any
type (C23 will allow {}).
What I had in mind was not the implicit cast from any integer literal
to other scalar types. But back these days the folks who handled that
told us that the 0 was a specific value, especially in the context of pointers (where, IIRC, the NULL pointer could have a non-0 decimal
value, but using 0 would not act as decimal 0 but as NULL-pointer).
In other words; however NULL was defined you could use p=NULL or p=0
with the same result.
(But since this had been just second hand information that I hadn't
checked myself I'm asking.)
On 18/02/2024 09:09, Michael S wrote:...
Short-named local vars are easier to read, too."i" is effectively a keyword, and "i=0" was picked up as one of the most common sequences in C by some sort of analysis. I think it was for compression. Just out "int i;" at the top and you have it in scope and
That is, as long as they are truly local, rather than declared at the
top in the style advocated by Malcolm (and by bart too?).
handy. And don't decare it in the loop because you can't then do
for (i = 0; i < N; i++)
if(!x[i])
break;
if (i == N)
On 18/02/2024 02:28, Lawrence D'Oliveiro wrote:
This is why C++ defined four different kinds of casting.
It was certainly good to separate the different types of casts.
Reintepreting bits is safe. Obviously you can do it in a way that gets
it wrong. But that is true of all computer code.
Desktop calcualtors meant for accountants, where 'plus-equals' is a
single key ... now they are impossible to use.
It could well be a surprise to non-experts that there is a function
"hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".
And it would certainly be a surprise to non-experts that the dedicated "hypot" function is far slower than the hand-written version.
Do you know of any C compilers or standalone tools that give this kind
of warning based on spacing? I don't.
On 16/02/2024 23:10, Lawrence D'Oliveiro wrote:
I see you had to shorten the variable names as well. Descriptive
layout *and* names too much for you?
Keep local variable names short and snappy is part of knowing how to
write readable code.
That’s about making the code easier to write, not easier to read. Don’t >> confuse the two. And don’t assume that the first has more importance
than the second.
It is easier to type "i" than "histogram_counter".
But it also makes a
long expression with more than one index operation in it easier to read.
On 18/02/2024 14:46, David Brown wrote:
On 18/02/2024 03:40, Lawrence D'Oliveiro wrote:My sister used to be maths teacher and she taught Bodmas. I remember
On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:Having been educated in Britain, I have never heard of "Bodmas" or
(I don't know the terms Bodmas/Bidmas, though. ...
We learned BODMAS, too. Although I remember the “O” stood for “Of”, as in
implied multiplication. So that binds more tightly than division (“D”), >>> which in turn binds more tightly than explicit multiplication (“M”). So >>> for example
a ÷ b(c + d)
should be interpreted as
a ÷ (b(c + d))
while
a ÷ b × (c + d)
should be interpreted as
(a ÷ b) × (c + d)
"Bidmas". I don't recall any mnemonic for the rules of precedence in
normal arithmetic.
because she pointed out that there was some inconsistency in it which had confused a child, but I can't remember what that was, I think it was ti do with unary minus.
Brackets, of, division, multiplication, addition, subtraction. "of" doesn't really appear in school mathematical expressions and was mainly to make it pronouceable, and it is now "Bidmas" where "i" is "index", meaning
exponent.
On 18.02.2024 08:48, Malcolm McLean wrote:
On 18/02/2024 01:22, Keith Thompson wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:Anyone who either thinks that the rule to to apply the operations in
[...]
In computer programs it is normally acceptable to write a = b + c * d
and because programs contain so many similar expressions, and because
the reader is another programmer and knows that the meaning is
constrained by the language as well as by convention, it will not
cause any confusion. But in a non-computer, non-professional
mathematical context, it is too likely to cause confusion, and you
must write a = b + (c * d).
What audience are you writing for that knows that "*" means
multiplication but won't understand "a = b + c * d;"?
sequence from left to right, or thinks that the writer may be using this
rule, or who thinks that if you enter the expression into a calculator,
the calculator is always right.
We probably should fall back to calculators (and interfaces) with
RPN input; this solves not only the precedence "problem" but also
the parenthesis "problem". :-)
On 18/02/2024 14:46, David Brown wrote:
On 18/02/2024 03:40, Lawrence D'Oliveiro wrote:My sister used to be maths teacher and she taught Bodmas. I remember
On Sun, 18 Feb 2024 02:16:39 +0100, Janis Papanagnou wrote:
(I don't know the terms Bodmas/Bidmas, though. ...
We learned BODMAS, too. Although I remember the “O” stood for “Of”, >>> as in
implied multiplication. So that binds more tightly than division (“D”), >>> which in turn binds more tightly than explicit multiplication (“M”). So >>> for example
a ÷ b(c + d)
should be interpreted as
a ÷ (b(c + d))
while
a ÷ b × (c + d)
should be interpreted as
(a ÷ b) × (c + d)
Having been educated in Britain, I have never heard of "Bodmas" or
"Bidmas". I don't recall any mnemonic for the rules of precedence in
normal arithmetic.
because she pointed out that there was some inconsistency in it which
had confused a child, but I can't remember what that was, I think it was
ti do with unary minus.
Brackets, of, division, multiplication, addition, subtraction. "of"
doesn't really appear in school mathematical expressions and was mainly
to make it pronouceable, and it is now "Bidmas" where "i" is "index",
meaning exponent.
In written maths, you can use spacing and free arrangement of symbolsI read a lot of mathematical papers that I haven't been formally trained
to indicate precedence. But you should be very careful of mixing
division and multiplication operators unless it is clear from the
layout - the way people interpret these things differ. Different
countries have different rules, and the rules change over time.
how to read or understand, and it is often challenging. But precedence
is seldom a difficulty.
I've always seen it rendered as "orders". I think "indexes" is better,
but it does not fix the basic problem.
And, for the record, I was never taught it.
On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:
It could well be a surprise to non-experts that there is a function
"hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".
What kind of programmer is it, that it would be so easy to surprise them
just by pointing out something in the documentation?
And yet they can remember the mathematical formula for a hypotenuse?
And it would certainly be a surprise to non-experts that the dedicated
"hypot" function is far slower than the hand-written version.
Most of the time, they wouldn’t notice. Particularly since the function is designed to keep them out of trouble.
If you need an efficient way to calculate such hypotenuses, the function "hypot" will get you /into/ trouble.
My claim is that no one would feel the need to add "/*if*/" comments to closing brackets unless they felt the code was not clearly
comprehensible without such comments. I am saying that /you/ write
/your/ code as though /you/ think your own code is hard to comprehend.
... brackets, orders ...
On 18/02/2024 22:34, Ben Bacarisse wrote:
[BODMAS]
I've always seen it rendered as "orders". I think "indexes" is better,
but it does not fix the basic problem.
And, for the record, I was never taught it.
Just curious - Were you taught SOHCAHTOA for trig? I always found that easy to remember.
On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:
... brackets, orders ...
“Of” (implied multiplication), not “orders”.
On 18/02/2024 22:34, Ben Bacarisse wrote:
[BODMAS]
I've always seen it rendered as "orders". I think "indexes" is better,
but it does not fix the basic problem.
And, for the record, I was never taught it.
Just curious - Were you taught SOHCAHTOA for trig? I always found that
easy to remember.
On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:
It could well be a surprise to non-experts that there is a function
"hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".
[...]
If you need an efficient way to calculate such hypotenuses, the function "hypot" will get you /into/ trouble. Typical use-cases would be in
games or graphics programming. The range issues are totally irrelevant,
and you need a final accuracy of your calculations to the nearest pixel
- you don't care about the LSB's (even for single-precision floats). But
you /do/ care about speed.
[...]
On 18/02/2024 14:31, Janis Papanagnou wrote:
So "manipulate" is the wrong word. You can't create or modify a
But you don't "manipulate" hierarchies with a dynamic_cast;
hierarchy with a cast. But you can obtain access to members in strange
ways.
The replies to your tendentious advice seem to be vying for maximum obfuscation. This should not written as a 'for' loop at all; it's a
natural 'while' loop:
On 18/02/2024 14:54, Janis Papanagnou wrote:
On 18.02.2024 13:09, Malcolm McLean wrote:x is an array of given data which contains scalars, that is conventional
for (i = 0; i < N; i++)
if(!x[i])
break;
if (i == N)
[...]
You could of course use a semantical name and keep variables localized
[ my code, using 'null_found', snipped ]
(Of course you should find a better, more sensible name for the !x[i]
condition, which I cannot guess from the few lines above.)
and you ought to be able to work that out. On loop exit i will be set to
the index of the first zero value, or N if no zero is found, and we then
test for the latter. It should be perfectly obvious to anyone with any experience what is going on, and it's a perfectly normal thing to need
to so. [...]
On Sun, 18 Feb 2024 15:31:33 +0100, Janis Papanagnou wrote:
On 18/02/2024 02:28, Lawrence D'Oliveiro wrote:
This is why C++ defined four different kinds of casting.
It was certainly good to separate the different types of casts.
Also, they had distinctive names that could be searched for in the code.
The separation of casts in C++ helps locating critical places.
(In C with the two parenthesis syntaxes that was a nightmare.)
On 18.02.2024 23:09, Lawrence D'Oliveiro wrote:
Also, they had distinctive names that could be searched for in the
code.
Indeed. - That's why I wrote explicitly (you snipped that part)...
The separation of casts in C++ helps locating critical places.
...where "locating" meant what you also expressed with "searched".
They completely avoided using
the 'float' types in Nethack and did all arithmetic in integer ...
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:
... brackets, orders ...
“Of” (implied multiplication), not “orders”.
You may have been taught that (why?) but an online search suggests that
that is not what gets taught.
On Sun, 18 Feb 2024 15:59:28 +0100, David Brown wrote:
It could well be a surprise to non-experts that there is a function
"hypot" in the C library, rather than just writing "sqrt(x*x + y*y)".
What kind of programmer is it, that it would be so easy to surprise them
just by pointing out something in the documentation?
On 18/02/2024 23:38, Lawrence D'Oliveiro wrote:
On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:I rarely find that with C. Usually each statement or operator compiles
If you need an efficient way to calculate such hypotenuses, the
function "hypot" will get you /into/ trouble.
Tip: something that programmers *do* frequently find surprising is that
their intuitions over which parts of their code to optimize and which
ones not to are all too frequently wrong.
to a single machine instruction.
Our maths teacher was Selby Brock (a
brilliant man who taught that the earth was flat),
On 18/02/2024 22:34, Ben Bacarisse wrote:
[BODMAS]
I've always seen it rendered as "orders". I think "indexes" is better,
but it does not fix the basic problem.
And, for the record, I was never taught it.
Just curious - Were you taught SOHCAHTOA for trig? I always found that
easy to remember.
On Mon, 19 Feb 2024 02:14:43 +0000, Ben Bacarisse wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
On Sun, 18 Feb 2024 22:34:06 +0000, Ben Bacarisse wrote:
... brackets, orders ...
“Of” (implied multiplication), not “orders”.
You may have been taught that (why?) but an online search suggests that
that is not what gets taught.
I’m not sure why. Given that exponentiation is conventionally denoted by placement, e.g.
b + c
a
there cannot possibly be any ambiguity about how the binding is supposed
to work.
On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:
If you need an efficient way to calculate such hypotenuses, the function
"hypot" will get you /into/ trouble.
Tip: something that programmers *do* frequently find surprising is that
their intuitions over which parts of their code to optimize and which ones not to are all too frequently wrong.
On Sun, 18 Feb 2024 16:14:23 +0100, David Brown wrote:
My claim is that no one would feel the need to add "/*if*/" comments to
closing brackets unless they felt the code was not clearly
comprehensible without such comments. I am saying that /you/ write
/your/ code as though /you/ think your own code is hard to comprehend.
No, you originally said “... if you need to do that with your "if" statements, your style is an incomprehensible mess”. So the “incomprehensible mess” nonsense is *your* claim, not mine, and *you* are the one who needs to back it up, not me.
On 18.02.2024 22:07, Ben Bacarisse wrote:
The replies to your tendentious advice seem to be vying for maximum
obfuscation. This should not written as a 'for' loop at all; it's a
natural 'while' loop:
Yes, but the original post contained an specific for() based example
and the topic was about local declaration not about the best control construct.
On 18/02/2024 23:38, Lawrence D'Oliveiro wrote:
On Sun, 18 Feb 2024 23:53:39 +0100, David Brown wrote:
If you need an efficient way to calculate such hypotenuses, the function >>> "hypot" will get you /into/ trouble.
Tip: something that programmers *do* frequently find surprising is that
their intuitions over which parts of their code to optimize and which ones >> not to are all too frequently wrong.
I rarely find that with C. Usually each statement or operator compiles
to a single machine instruction.
I’m not sure why. Given that exponentiation is conventionally denoted by placement, e.g.
b + c
a
there cannot possibly be any ambiguity about how the binding is supposed
to work.
On 19/02/2024 07:58, David Brown wrote:
On 19/02/2024 03:26, Malcolm McLean wrote:Come on. Some respect and some intelligence. If I say he was a brilliant
Our maths teacher was Selby Brock (a brilliant man who taught that
the earth was flat),
Isn't that somewhat of an oxymoron? I had one primary teacher that
taught that there were 10 planets (Pluto was still called a planet at
the time, and he counted the sun as a planet) and another that did not
consider the sun to be a star or the earth to be a planet. But these
were /not/ good teachers.
It's conceivable that this person was a good teacher of maths, but
that's different from being a good teacher in general.
man I wouldn't say that lightly, and he had very good reasons for
teaching that the Earth was flat. It was nonsense, everyone knew it was nonsense, but no boy ever actually managed to prove that it was
nonsense, and that was the point.
But it perfectly justified "Selby always teaches crap".
On 19.02.2024 06:17, Lawrence D'Oliveiro wrote:
I’m not sure why. Given that exponentiation is conventionally denoted by >> placement, e.g.
b + c
a
there cannot possibly be any ambiguity about how the binding is supposed
to work.
It is relevant, e.g. in 4^3^2 which is 4^(3^2) and not (4^3)^2
(when "placement" is the representation in writings), and in computer formulas it's anyway relevant when everything is on one line.
Janis
On 19/02/2024 04:14, Janis Papanagnou wrote:
Is a constructor a cast?
BTW; a mistake of mine was to write inaccurately "C with the two
parenthesis syntaxes"; it was, I think, C++ that added the second
form that made it possible that a cast looks like a function call.
Frankly, I don't know whether C also added that.
We have a class called "fixed" which represents reals in binary using a
fixed binary point. So obviously we shall write a constructor for it so
we can easily and conviently obtain values like "0.5", which shall take
a double. And if we all it exlicitly it's
fixed x;
x = fixed(0.5);
and to all intents and purposes we've just cast a double to a fixed.
And in fact
x = (fixed) 0.5;
will call the same constructor.
There are teachers who hold all kinds of weird and nonsensical beliefs,
just as in many other areas of life. People can believe what they want
- freedom of religion is important. But what they /teach/, or how they otherwise interact with people that they have power or authority over,
is a different matter.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
(int)x vs. int(x)
My question was about newer C standards supporting the second form;
a quick test shows that C++ (of course) does, but my C version doesn't.
But I (still) don't know about the current C standards.
C does not support C++-style int(x) casts in any version up to and
including C23. The only form of cast in C is (type-name) expression.
On 18/02/2024 23:06, Richard Harnden wrote:
On 18/02/2024 22:34, Ben Bacarisse wrote:
[BODMAS]
I've always seen it rendered as "orders". I think "indexes" is better,
but it does not fix the basic problem.
And, for the record, I was never taught it.
Just curious - Were you taught SOHCAHTOA for trig? I always found that easy to remember.
Never heard that one - is it thought of as one long word??
Just as we're on the subject, a friend of mine at high school was pleased with himself for inventing
what might be the most useless maths mnemonic ever:
Smelly Armpits Cause Termites
ok, it's memorable for sure, no problem on that front! But I was baffled why he thought it
important to have a mnemonic for what it explains. (Plus it's hardly logical (mathematically) even
if you know what it's explaining!)
ob. Puzzle - what was his mnemonic helping him remember? [hint: it's trig related]
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
Reminding us of:
|
|
Cosine | All
|
|
--------------+--------------
|
|
Tangent | Sine
|
|
That's right, it's helping us remember which trig functions are
positive in each of the four quadrants!
Um, don't ask....! :)
Is a constructor a cast?
I think you underestimate the ability of schoolkids to get things wrong!
ab² could easily be misinterpreted as (ab)².
In particular, there's lots of programmers not
particularly interested in or familiar with the math library. Most of
those would consider hypot() an obscure function. I was working on a
NASA contract on scientific software when I introduced hypot() into a function, and at least half the people who reviewed the code needed to
be reminded what it does.
On 19.02.2024 06:17, Lawrence D'Oliveiro wrote:
there cannot possibly be any ambiguity about how the binding is
supposed to work.
It is relevant, e.g. in 4^3^2 which is 4^(3^2) and not (4^3)^2 ...
Now, can we find a good mnemonic for C's operator precedence levels?
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
In this particular case, I'd just use 0. If for some reason I
needed to make it explicitly of type uint64_t (say, for an
argument to a variadic function), I'd write `(uint64_t)0`.
Ick. At least write '(uint64_t){ 0 }' rather than casting.
Why?
Casts are dangerous. Besides being dangerous, in many cases
casts are accidents waiting to happen. Writing casts at the drop
of a hat is a bad habit. A good programming practice is to avoid
using a cast whenever feasible. Using a compound literal isn't a
lot better than just a raw cast, but it does at least provide a
little extra safety because it allows only "safe" conversions.
Seeing a cast in open code should always raise a red flag,
especially when, as in this case, it's easy to find a safer
alternative.
I disagree in this case. Yes, casts certainly can be dangerous,
especially those involving pointers, and I'd say that all casts
should be looked on with some suspicion. But anyone who knows C
can recognize that casting a constant 0 to an integer type is not
in any way dangerous.
[...]
Now, can we find a good mnemonic for C's operator precedence levels?
Extra credit if left/right associativity is also covered.
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
On 19/02/2024 00:39, Lawrence D'Oliveiro wrote:
On Sun, 18 Feb 2024 16:14:23 +0100, David Brown wrote:
My claim is that no one would feel the need to add "/*if*/" comments
to closing brackets unless they felt the code was not clearly
comprehensible without such comments. I am saying that /you/ write
/your/ code as though /you/ think your own code is hard to comprehend.
No, you originally said “... if you need to do that with your "if"
statements, your style is an incomprehensible mess”. So the
“incomprehensible mess” nonsense is *your* claim, not mine, and *you*
are the one who needs to back it up, not me.
I have explained what I meant, and given my reasoning. If you don't understand that, or don't like it, feel free to ignore it.
(Note that I did not say your style is an incomprehensible mess. I said
/if/ you need these comments, it is a mess.
Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:
Your example shows why I never liked this sort of "help". Remembering
where to start and what order to label the quadrants is harder (for me)
than knowing how trig functions work.
Now, can we find a good mnemonic for C's operator precedence levels?
Extra credit if left/right associativity is also covered. (Few! On
topic again.)
On Mon, 19 Feb 2024 07:54:15 +0000, Malcolm McLean wrote:
Is a constructor a cast?
One thing should be clear: there should not be any confusion between safe
and unsafe type conversions.
In Modula-2, for unsafe conversions you had CAST(«type», «expr»), which you had to import from SYSTEM before you could use it. So it was easy to
scan through the code to find instances of its use.
In C++, you have const_cast and reinterpret_cast, which while they don’t need to be imported from anywhere, are still sufficiently distinctive
names.
The C syntax is very difficult to search for. And of course it mixes up
both safe (e.g. int⟷float) and unsafe conversions in the same syntax, so checking for the latter becomes doubly hard.
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
On Mon, 19 Feb 2024 00:39:00 -0500, James Kuyper wrote:
In particular, there's lots of programmers not
particularly interested in or familiar with the math library. Most of
those would consider hypot() an obscure function. I was working on a
NASA contract on scientific software when I introduced hypot() into a
function, and at least half the people who reviewed the code needed to
be reminded what it does.
Interesting that they would be qualified to review maths-intensive code, without having to be familiar with the maths library.
On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
I learned
crazy all
teachers are science
from a math teacher who was Scottish. Someone in the class piped up
with "all Scottish teachers are crazy", to great laughter.
David Brown <david.brown@hesbynett.no> writes:
On 20/02/2024 01:05, Ben Bacarisse wrote:
Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:
Your example shows why I never liked this sort of "help". Remembering
where to start and what order to label the quadrants is harder (for me)
than knowing how trig functions work.
Same for me. The trick to getting the signs of sins right is to think of
circles, not triangles, when doing trig. Then it is all completely
obvious.
Now, can we find a good mnemonic for C's operator precedence levels?
Extra credit if left/right associativity is also covered. (Few! On
topic again.)
People Pick Unix 'Cause Make And Bake 'Re Easy ....
Primary, Postfix, Unary, Cast, Multiplicative, Additive, Bitwise shift,
Relational, Equality ...
A valiant effort, but why is cast singled out and put after other unary operators? Also B (=Bitwise) for shift when there are so many bit-wise operators? It would be better if "sh" were in the mnemonic there as in
"make and shell"?
I haven't got to the bitwise operators yet!
They, of course, are the ones that trip people up since they have unexpectedly odd precedence due to their use in B as the sole way to get logical connectives. I happened to learn B before C, so that was not so
hard for me to internalise.
For me, pretty much the only one I'd have to look up (though only in a
year or two, since I've recently been reminded!) is ^ vs |.
On 20/02/2024 01:05, Ben Bacarisse wrote:
Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:
Your example shows why I never liked this sort of "help". Remembering
where to start and what order to label the quadrants is harder (for me)
than knowing how trig functions work.
Same for me. The trick to getting the signs of sins right is to think of circles, not triangles, when doing trig. Then it is all completely
obvious.
Now, can we find a good mnemonic for C's operator precedence levels?
Extra credit if left/right associativity is also covered. (Few! On
topic again.)
People Pick Unix 'Cause Make And Bake 'Re Easy ....
Primary, Postfix, Unary, Cast, Multiplicative, Additive, Bitwise shift, Relational, Equality ...
I haven't got to the bitwise operators yet!
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
I learned
crazy all
teachers are science
from a math teacher who was Scottish. Someone in the class piped up
with "all Scottish teachers are crazy", to great laughter.
I don't think it worked! I was maybe too subtle in my last post, but
you have to remember something entirely arbitrary with this sort of
thing -- where to start and the order of going round (or otherwise
naming) the quadrants. All the posted examples I've see have the C and
S quadrants swapped over.
On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
The standard doesn't describe operator precedence levels. It provides
grammar rules, and precedence must be inferred from the grammar. I've
found that it is not widely understood how to infer precedence from the grammar.
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
I learned
crazy all
teachers are science
from a math teacher who was Scottish. Someone in the class piped up
with "all Scottish teachers are crazy", to great laughter.
I don't think it worked! I was maybe too subtle in my last post, but
you have to remember something entirely arbitrary with this sort of
thing -- where to start and the order of going round (or otherwise
naming) the quadrants. All the posted examples I've see have the C and
S quadrants swapped over.
On 2024-02-20, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
The standard doesn't describe operator precedence levels. It provides
grammar rules, and precedence must be inferred from the grammar. I've
found that it is not widely understood how to infer precedence from the
grammar.
Really? But it's dead trivial.
The parent production has lower precedence than the child; e.g.
additive_expression '+' multiplicative_expression.
The '+' has precedence over '*' and '/' because the
multiplicative_expression is an indivisible symbol in the
additive_expression rule. The rule does not "see" the multiplicative
symbols at all, but a multiplicative_expression phrasal unit.
That's basically it.
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
[...]
Now, can we find a good mnemonic for C's operator precedence levels?
Extra credit if left/right associativity is also covered.
Let me ask, which areas give people the most trouble, or where do
they find that they need help remembering? My reason for asking is
I myself find most of C's expression syntax behaves the way I expect
without having to think about it, so I need relatively few memory
aids to feel confident in knowing the whole stack. But what are the stumbling blocks for other folks?
C mixes up some operators between (1) and (2), that's one thing.
For example, ^ is bizarrely lower precedence than ==.
On 2/20/24 12:06, Kaz Kylheku wrote:
On 2024-02-20, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
The standard doesn't describe operator precedence levels. It provides
grammar rules, and precedence must be inferred from the grammar. I've
found that it is not widely understood how to infer precedence from the
grammar.
Really? But it's dead trivial.
The parent production has lower precedence than the child; e.g.
additive_expression '+' multiplicative_expression.
The '+' has precedence over '*' and '/' because the
multiplicative_expression is an indivisible symbol in the
additive_expression rule. The rule does not "see" the multiplicative
symbols at all, but a multiplicative_expression phrasal unit.
That's basically it.
I have no trouble with it, but I've seen other people have trouble. And
of course, it gets particularly tricky with regard to a few special cases:
primary-expression:
( expression )
postfix-expression:
postfix-expression [ expression ]
conditional-expression:
logical-OR-expression ? expression : conditional-expression
bart <bc@freeuk.com> writes:
[...]
I like to intuitively think of binary operators as belonging to three[...]
groups:
(1) Within expressions (arithmetic, but also bitwise ops)
(2) Comparisons (with one precedence level)
(3) Logical and/or (only 2 precedence levels)
All (1) have higher precendence than (2), which are higher than
(3). (In my code, groups (2) and (3) mostly occur in conditional
expressions such as 'f (expr)'.)
"Within expressions" is an odd way to describe it, since all operators
are within expressions.
On 2024-02-20, bart <bc@freeuk.com> wrote:
C mixes up some operators between (1) and (2), that's one thing.
For example, ^ is bizarrely lower precedence than ==.
Yes, this is an ancient mistake that was acknowledged by D. Ritchie
decades ago.
It's an unfortunate thing that is hard to change.
The most harm that came out of it is, I think, not the programming
bugs, but the endless debate.
It's not impossible to change. Basically first we would have to
mark the current precedence deprecated, and require a diagnostic
for programw which rely on it.
For instance the expression a == b & c == d would require a diagnostic, similar to the optional one can obtain get anyway from some popular compilers.
Then, after a long period of obsolescence and diagnosis, perhaps 25
years or more, new rules could be put in. a == b & c == d would not
longer require a diagnostic, but silently parse as (a == (b & c)) == d.
IMO, it would have been a good idea had ANSI C 89 taken the above obsolescence step. By C11, if not C99, we could have been rid of the precedence infelicities.
The problem with requiring a diagnostic is that the standard doesn't distinguish errors and warnings. A program which requires a diagnostic
is erroneous. If it is translated and executed anyway, its behavior is undefined.
You can't say that a == b & c == d is correct, and parses as (a == b ) &
(c == d), while at the same time demanding a diagnostic. That's contradictory: if it requires a diagnostic, it is incorrect.
The standard would have to sharpen its knife and introduce the concept
of informational diagnostics which don't indicate an incorrect
situation, but only some deprecated situation.
On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
The standard doesn't describe operator precedence levels. It provides
grammar rules, and precedence must be inferred from the grammar. I've
found that it is not widely understood how to infer precedence from the grammar.
For example, ^ is bizarrely lower precedence than ==.
Yet C puts the precedence of << and >> the other side of + and -. This
means that:
1 << 2 + 3
is 1<<(2+3) or 32, not (1<<2)+3 or 7.
Another one is ?: as in:
a ? b ? c : d : e // or:
a ? b : c ? d : e
With more complex terms, it's easy to get lost. Although this one is not
so much about precedence; I wouldn't class it as an operator all, and
would insist on parentheses so that the boundaries of this 3-way
construct are absolutely clear.
On Tue, 20 Feb 2024 10:11:19 +0000, Malcolm McLean wrote:
this will be the problem than that somone will need an accurate value
for a vector with members pushing DBL_MAX, and this will be the problem.
Remember that one of the key goals of IEEE754 was to minimize surprises
for those who are not complete wizards at numerical techniques (i.e.
nearly all of us).
this will be the problem than that somone will need an accurate value
for a vector with members pushing DBL_MAX, and this will be the problem.
On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:
*resultptr++ =
alpha << 24
|
(b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
|
(g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
|
(r << 3 | (r & 0xE0) >> 5) * alpha / 255;
You're using | instead of + ...
final PointF ThisMouse =
ThisMouse1 != null ?
ThisMouse2 != null ?
new PointF
(
(ThisMouse1.x + ThisMouse2.x) / 2.0f,
(ThisMouse1.y + ThisMouse2.y) / 2.0f
)
:
ThisMouse1
:
ThisMouse2;
But you wouldn't write that would you?
On Tue, 20 Feb 2024 17:20:00 +0000, bart wrote:
For example, ^ is bizarrely lower precedence than ==.
That I agree is bizarre. Python quietly rearranges things, and I don’t think many C programmers have noticed.
Yet C puts the precedence of << and >> the other side of + and -. This
means that:
1 << 2 + 3
is 1<<(2+3) or 32, not (1<<2)+3 or 7.
This seems to work reasonably well, even in complex cases, e.g.
*resultptr++ =
alpha << 24
|
(b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
|
(g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
|
(r << 3 | (r & 0xE0) >> 5) * alpha / 255;
Another one is ?: as in:
a ? b ? c : d : e // or:
a ? b : c ? d : e
With more complex terms, it's easy to get lost. Although this one is not
so much about precedence; I wouldn't class it as an operator all, and
would insist on parentheses so that the boundaries of this 3-way
construct are absolutely clear.
Indentation works, too:
final PointF ThisMouse =
ThisMouse1 != null ?
ThisMouse2 != null ?
new PointF
(
(ThisMouse1.x + ThisMouse2.x) / 2.0f,
(ThisMouse1.y + ThisMouse2.y) / 2.0f
)
:
ThisMouse1
:
ThisMouse2;
On Wed, 21 Feb 2024 00:33:21 +0000, bart wrote:
On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:
*resultptr++ =
alpha << 24
|
(b << 3 | (b & 0xE0) >> 5) * alpha / 255 << 16
|
(g << 2 | (g & 0xC0) >> 6) * alpha / 255 << 8
|
(r << 3 | (r & 0xE0) >> 5) * alpha / 255;
You're using | instead of + ...
Of course; that seems the natural one to use, when concatenating bit
fields.
final PointF ThisMouse =
ThisMouse1 != null ?
ThisMouse2 != null ?
new PointF
(
(ThisMouse1.x + ThisMouse2.x) / 2.0f,
(ThisMouse1.y + ThisMouse2.y) / 2.0f
)
:
ThisMouse1
:
ThisMouse2;
But you wouldn't write that would you?
I did. That is from actual, working code.
On 2/19/2024 11:21 AM, Mike Terry wrote:
On 19/02/2024 00:06, Mike Terry wrote:
On 18/02/2024 23:06, Richard Harnden wrote:
On 18/02/2024 22:34, Ben Bacarisse wrote:
[BODMAS]
I've always seen it rendered as "orders". I think "indexes" is better, >>>>> but it does not fix the basic problem.
And, for the record, I was never taught it.
Just curious - Were you taught SOHCAHTOA for trig? I always found that easy to remember.
Never heard that one - is it thought of as one long word??
Just as we're on the subject, a friend of mine at high school was pleased with himself for
inventing what might be the most useless maths mnemonic ever:
Smelly Armpits Cause Termites
ok, it's memorable for sure, no problem on that front! But I was baffled why he thought it
important to have a mnemonic for what it explains. (Plus it's hardly logical (mathematically)
even if you know what it's explaining!)
ob. Puzzle - what was his mnemonic helping him remember? [hint: it's trig related]
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
Reminding us of:
|
|
Cosine | All
|
|
--------------+--------------
|
|
Tangent | Sine
|
|
That's right, it's helping us remember which trig functions are positive in each of the four
quadrants!
Um, don't ask....! :)
What about using cos for x and sin for y therefore:
cos(0) = 1
Would be on the "right side" assuming:
_____________________
+y
|
|
|
|
|
^
-x -----------<0>----------- +x
v
|
|
|
|
-y
_____________________
?
On Tue, 20 Feb 2024 03:32:19 -0500, James Kuyper wrote:
On 2/19/24 20:37, Lawrence D'Oliveiro wrote:
On Tue, 20 Feb 2024 00:05:56 +0000, Ben Bacarisse wrote:
Now, can we find a good mnemonic for C's operator precedence levels?
“RTFM”.
The standard doesn't describe operator precedence levels. It provides
grammar rules, and precedence must be inferred from the grammar. I've
found that it is not widely understood how to infer precedence from the
grammar.
Wasn’t BNF covered in one of your undergraduate CS courses?
My point was that I've talked with many people who found it less obvious
than you or I do.
On 21/02/2024 00:45, Lawrence D'Oliveiro wrote:
On Wed, 21 Feb 2024 00:33:21 +0000, bart wrote:
On 20/02/2024 23:03, Lawrence D'Oliveiro wrote:
final PointF ThisMouse =
ThisMouse1 != null ?
ThisMouse2 != null ?
new PointF
(
(ThisMouse1.x + ThisMouse2.x) / 2.0f,
(ThisMouse1.y + ThisMouse2.y) / 2.0f
)
:
ThisMouse1
:
ThisMouse2;
But you wouldn't write that would you?
I did. That is from actual, working code.
So why didn't you use 'if' and 'else'?
On 20/02/2024 02:19, Tim Rentsch wrote:
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
[...]
Now, can we find a good mnemonic for C's operator precedence levels?
Extra credit if left/right associativity is also covered.
Let me ask, which areas give people the most trouble, or where do
they find that they need help remembering? My reason for asking is
I myself find most of C's expression syntax behaves the way I expect
without having to think about it, so I need relatively few memory
aids to feel confident in knowing the whole stack. But what are the
stumbling blocks for other folks?
I like to intuitively think of binary operators as belonging to three
groups:
(1) Within expressions (arithmetic, but also bitwise ops)
(2) Comparisons (with one precedence level)
(3) Logical and/or (only 2 precedence levels)
All (1) have higher precendence than (2), which are higher than (3). (In
my code, groups (2) and (3) mostly occur in conditional expressions such
as 'f (expr)'.)
C mixes up some operators between (1) and (2), that's one thing.
For example, ^ is bizarrely lower precedence than ==.
Even within the same group (1), I think of << and >> as scaling
operators of the same rank as * and /, since they really do the same job
(any shift can be implemented with multiple or divide by a power of two).
Yet C puts the precedence of << and >> the other side of + and -. This
means that:
1 << 2 + 3
is 1<<(2+3) or 32, not (1<<2)+3 or 7.
Another one is ?: as in:
a ? b ? c : d : e // or:
a ? b : c ? d : e
With more complex terms, it's easy to get lost. Although this one is not
so much about precedence; I wouldn't class it as an operator all, and
would insist on parentheses so that the boundaries of this 3-way
construct are absolutely clear.
With parentheses, I /believe/ the correct grouping that corrresponds is repectively:
(a ? (b ? c : d) : e)
(a ? b : (c ? d : e))
Now I can change 'I believe' to 'I know'.
Remember this is not just about working with C. People may work on
different languages with their own rules.
`2 + 3 * 4` is near-universally evaluated as 14. With `1 << 2 + 3` most languages I managed to try on rextester.com (which supported infix
`<<`), also gave C's result of 32.
This means a lot of languages that have perpetuated C's bad choices.
A few languages however did not just blindly follow C, such as Pascal,
Go and Swift; those gave a result of 7.
On 2024-02-20, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2024-02-19, Mike Terry <news.dead.person.stones@darjeeling.plus.com> wrote:
In case anyone was curious...
|
|
Cause | Armpits
|
|
--------------+--------------
|
|
Termites | Smelly
|
|
I learned
crazy all
teachers are science
from a math teacher who was Scottish. Someone in the class piped up
with "all Scottish teachers are crazy", to great laughter.
I don't think it worked! I was maybe too subtle in my last post, but
you have to remember something entirely arbitrary with this sort of
thing -- where to start and the order of going round (or otherwise
naming) the quadrants. All the posted examples I've see have the C and
S quadrants swapped over.
Like a Chat AI robot, I just followed my interlocutor's example,
and pretended it's right.
For a moment, I wondered why the words are going clockwise (negative rotation) but didn't give it a moment's thought beyond that.
Part of the value of the "all science teachers are crazy" mnemonic is
that it starts with the first quadrant and follows the positive angle.
You will not get it wrong, unless you're preloaded with a wrong example
and don't think about it.
If you think about it for a millisecond, of course sin() is positive
over the first 180 degrees, but since cos() starts high, that
function drops and crosses zero at 90. If you know this simple
thing, you don't need the mnemonic.
[...]
On 20/02/2024 01:05, Ben Bacarisse wrote:
Mike Terry <news.dead.person.stones@darjeeling.plus.com> writes:
[...]
Your example shows why I never liked this sort of "help".
Remembering where to start and what order to label the quadrants
is harder (for me) than knowing how trig functions work.
Same for me. The trick to getting the signs of sins right is to
think of circles, not triangles, when doing trig. Then it is all
completely obvious.
Now, can we find a good mnemonic for C's operator precedence
levels? Extra credit if left/right associativity is also
covered. (Few! On topic again.)
For me, pretty much the only one I'd have to look up (though only
in a year or two, since I've recently been reminded!) is ^ vs |.
On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
If I were designing a new language, I'd consider using ":=" for
assignment, "==" for equality, and not using "=" for anything.
In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
means assignment, and "==" either doesn't exist or means equality. I'd avoid "=" because it's ambiguous across languages (and that's almost entirely C's fault, inherited from B).
Some of the credit must go to classic BASIC!
I seem to remember than in classic, line-numbered BASICs on 8 bit
micros, the = token was used both for assignment and comparison!
300 I = I + 1
310 IF I = 10 GOTO 340
If you have a dedicated assignment statement, you can pull this kind
of stunt. Just like C can distinguish initialization from assignment.
On Fri, 9 Feb 2024 22:14:19 -0000 (UTC), Kaz Kylheku <433-929-6894@kylheku.com> wrote:
On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
If I were designing a new language, I'd consider using ":=" for
assignment, "==" for equality, and not using "=" for anything.
In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
means assignment, and "==" either doesn't exist or means equality.
I'd
avoid "=" because it's ambiguous across languages (and that's almost
entirely C's fault, inherited from B).
Some of the credit must go to classic BASIC!
BASIC itself predates (B and) C, but 8 bit micros are at least 5 years
I seem to remember than in classic, line-numbered BASICs on 8 bit
micros, the = token was used both for assignment and comparison!
300 I = I + 1
310 IF I = 10 GOTO 340
too late.
If you have a dedicated assignment statement, you can pull this kind
of stunt. Just like C can distinguish initialization from assignment.
And I'm pretty sure Dartmouth BASIC required LET var = expr, which
(more) clearly distinguished it from IF.
[...]
On 26.02.2024 10:22, dave_thompson_2@comcast.net wrote:
On Fri, 9 Feb 2024 22:14:19 -0000 (UTC), Kaz Kylheku
<433-929-6894@kylheku.com> wrote:
On 2024-02-09, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
If I were designing a new language, I'd consider using ":=" for
assignment, "==" for equality, and not using "=" for anything.
In (nearly?) all languages I'm aware of, ":=" either doesn't exist or
means assignment, and "==" either doesn't exist or means equality.
In Simula you have '=' (equality) and '==' (identity; for references),
and of course ':=' (value assignments) and ':-' (reference assignments).
I'd
avoid "=" because it's ambiguous across languages (and that's almost
entirely C's fault, inherited from B).
Some of the credit must go to classic BASIC!
Don't forget FORTRAN (appearing before BASIC). And here also the syntax ambiguity it had with loops and assignments (but I forgot the details).
And I'm pretty sure Dartmouth BASIC required LET var = expr, which
(more) clearly distinguished it from IF.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (0 / 16) |
Uptime: | 161:39:18 |
Calls: | 10,385 |
Calls today: | 2 |
Files: | 14,057 |
Messages: | 6,416,500 |