Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How About Disallowing Assignments In Expressions?

946 views
Skip to first unread message

Lawrence D'Oliveiro

unread,
Feb 8, 2024, 7:39:16 PMFeb 8
to
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.

Malcolm McLean

unread,
Feb 8, 2024, 7:53:56 PMFeb 8
to
while( (ch = fgetc(fp)) != EOF)

is the idiomatic way of accessing a stream a character by character in
C. So you would disallow this.
--
Check out Basic Algorithms and my other books:
https://www.lulu.com/spotlight/bgy1mm

Kaz Kylheku

unread,
Feb 8, 2024, 8:13:37 PMFeb 8
to
Python's original solution is stupid. All they had to do is to use :=
for assignment, and leave = as a comparison.

... and that's what they did now, as of Python 3.8.

There is a := assignment that can be used in the middle of an
expression. This is given the idiotic nickname "walrus operator".

:= can be used in the middle of expressions.

Except they can't drop the old = assignment due to backward
compatibility.

Walrus is what should have been assignment in the first place.
But because Van Possum was coding Python in C, he just aped
some C choices into the language.

(I'm guessing that he knew that the first people to get their hands on
Python and popularize it would be C-and-Unix people, who would
balk at a := operator.)

By the way, assignment in the middle of expressions comes from Lisp.
Basically the idea that everything is an expression, even things
that perform side effects or behave like statements. The ternary
operator comes from Lisp: (if expr then else).

[CLISP]
[1]> (let ((i 0)) (list (incf i) (incf i) (incf i)))
(1 2 3)

You're unlikely to type setf or incf when you wanted a comparison.
ANSI Common Lisp is strictly evaluated so the above is required
to produce (1 2 3) and not (2 1 3) or whatever. Stuffing side
effects into Lisp expressions is less risky than in C.

(Not so with Scheme: in Scheme, the evaluation order of function
arguemnts is unspecified, like in C!)

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazi...@mstdn.ca

Lawrence D'Oliveiro

unread,
Feb 8, 2024, 9:10:45 PMFeb 8
to
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!

David Brown

unread,
Feb 9, 2024, 3:28:09 AMFeb 9
to
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.


Ben Bacarisse

unread,
Feb 9, 2024, 5:17:03 AMFeb 9
to
David Brown <david...@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).

--
Ben.

Richard Harnden

unread,
Feb 9, 2024, 5:36:27 AMFeb 9
to
This is what ChatGPT says ...

User
Can you list C language bugs, categorising them by what language
features would have made them either impossible or less likely.

ChatGPT
Certainly! Here are some common bugs in C categorized by language
features that could have prevented them or made them less likely:

Null Pointer Dereference:
Language Feature: Safe pointer handling like in Rust or smart pointers
in C++. Features like optional nullability annotations or language
constructs that enforce non-null pointers can help prevent null pointer
dereference bugs.

Buffer Overflows:
Language Feature: Bounds checking in arrays. Languages like Rust have
built-in checks to prevent buffer overflows at compile-time.
Safe string handling functions like those provided by libraries such as
Safe C String Library (SCL) or SafeLib.

Memory Leaks:
Language Feature: Automatic memory management like garbage collection or
smart pointers. Languages like Java, C#, and modern C++ with RAII
(Resource Acquisition Is Initialization) significantly reduce the
occurrence of memory leaks.

Use After Free:
Language Feature: Automated memory management, such as garbage
collection, or ownership tracking systems like those found in Rust's
ownership model.

Uninitialized Variables:
Language Feature: Initialization guarantees or compiler warnings for
uninitialized variables. Tools like static code analyzers or compilers
with strong type checking can help detect such issues.

Type Safety Violations:
Language Feature: Strong static typing. Languages like Java, C#, or Rust
enforce stronger type safety, reducing the likelihood of type-related bugs.

Race Conditions:
Language Feature: Built-in support for concurrent programming paradigms,
such as message passing (e.g., Erlang) or ownership model (e.g., Rust),
or immutability (e.g., functional programming languages like Haskell).

Integer Overflows:
Language Feature: Safe arithmetic operations. Languages like Rust
provide safe arithmetic operations that panic on overflow, preventing
undefined behavior.

Resource Management Issues (e.g., File Handles, Sockets):
Language Feature: RAII (Resource Acquisition Is Initialization) or using
constructs like "defer" in Go. Languages like Rust with its ownership
model can enforce proper resource management.

Unprotected Access to Shared Resources:
Language Feature: Mechanisms for synchronization and concurrent access
control, such as locks, semaphores, or higher-level constructs like
channels in Go or message passing in Erlang.

Floating Point Precision Errors:
Language Feature: Enhanced floating-point arithmetic support or
arbitrary-precision arithmetic libraries. Languages like Python or
libraries like GNU MPFR provide arbitrary-precision arithmetic, reducing
precision errors.

Pointer Arithmetic Errors:
Language Feature: Restricted or controlled pointer arithmetic. Safe
pointer operations and bounds checking can prevent pointer arithmetic
errors.

By incorporating these language features or using languages with
built-in protections against common programming errors, developers can
significantly reduce the likelihood of encountering these bugs.

Ben Bacarisse

unread,
Feb 9, 2024, 8:18:14 AMFeb 9
to
Richard Harnden <richard...@gmail.invalid> writes:

> On 09/02/2024 10:16, Ben Bacarisse wrote:
>> David Brown <david...@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).
>
> This is what ChatGPT says ...

Seriously? You do know how large language models work, yes?

--
Ben.

David Brown

unread,
Feb 9, 2024, 8:44:10 AMFeb 9
to
On 09/02/2024 11:16, Ben Bacarisse wrote:
> David Brown <david...@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 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!

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.

>
> * 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).
>

I would agree with that.

However, I /have/ seen such bugs in code that has been written and
deployed, precisely because even the most crude tests and static
checking where not employed.

Far and away the biggest steps towards "safe C" is for people to use
good development practices, including good testing, good static error
checking, appropriate training, code reviews, etc. The unfortunate
reality is that there are many programmers who don't use such practices,
or don't use them correctly. And I don't think a change to how
assignment works would make a noticeable difference to this much larger
and more general problem.


Richard Harnden

unread,
Feb 9, 2024, 9:09:04 AMFeb 9
to
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.

bart

unread,
Feb 9, 2024, 10:44:13 AMFeb 9
to
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.

(It's also a bit of a pain when implementing a language that allows it.)

David Brown

unread,
Feb 9, 2024, 10:57:32 AMFeb 9
to
On 09/02/2024 16:43, bart wrote:
> 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.

Yes. It's not used often IME, and would be easy to fix, but you only
need it once in a program to make such a suggestion a breaking change.

>
> But what is the problem with 'a = b = c'?

My preference is to do one thing at a time - then it's clear what is
going on. I think it is rare that you could make use of such chained
assignment, and even rarer where you could reasonably argue that it is
clearer than simply writing two separate lines. (And when you use a
"declare variables when you are ready to initialise them" style, it is
much more natural to use two lines.)

About the only time when I think you might say that chained assignment
is clearer is for very closely related variables set to zero :

int x, y, z;
x = y = z = 0;

I would probably be happy to throw that clear usage out in order to stop
people making unclear usage of chained assignment.

> The real problems with
> assignments inside expressions is when you accidentally use '=' instead
> of '=='. That's due to a poor choice of syntax.
>

That's a non-issue for anyone who can use a compiler with static error
checking, because it is almost always easy to spot automatically.

> 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.

Agreed 100%.

(I hope that didn't shock you too much!)


Kaz Kylheku

unread,
Feb 9, 2024, 11:36:06 AMFeb 9
to
On 2024-02-09, David Brown <david...@hesbynett.no> wrote:
> 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.

It was probably Lisp that introduced the idea of assignment being an
expression (due to everything being an expression). It's a safe
language, and not less safe on that account. This is because you are
vanishingly unlikely to accidentally write (setq a b) when you intended
(eq a b), and if that were to happen, another pair of reviewing eyes
would likely not gloss over it.

Python has now reintroduced a form of assignment you can use
in the middle of an expression; the token is := which is unlikely
to be used by mistake instead of an equality test or whatnot.

Keith Thompson

unread,
Feb 9, 2024, 12:10:00 PMFeb 9
to
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".

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */

Malcolm McLean

unread,
Feb 9, 2024, 12:22:28 PMFeb 9
to
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 "==".

Keith Thompson

unread,
Feb 9, 2024, 12:35:13 PMFeb 9
to
Malcolm McLean <malcolm.ar...@gmail.com> writes:
> 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 "==".

Are you sure you're not thinking of Pascal?

Fortan doesn't use := as far as I can tell. It uses = for assignment
and .EQ. (or ==) for equality. (I think the == form is relatively new;
it's there in Fortran 90.)

Kaz Kylheku

unread,
Feb 9, 2024, 12:38:27 PMFeb 9
to
On 2024-02-09, Keith Thompson <Keith.S.T...@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.

Keith Thompson

unread,
Feb 9, 2024, 12:49:34 PMFeb 9
to
Kaz Kylheku <433-92...@kylheku.com> writes:
> On 2024-02-09, Keith Thompson <Keith.S.T...@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.

One issue with C is that its syntax is what I think of as "dense".

In more verbose languages (Ada is an example), a typo is very likely to
result in an easily diagnosable syntax error. In C, many typos result
in syntactically valid code that means something different. Examples
are = vs ==, > vs >>, etc. Compilers can detect and warn about some
things that are likely to be typos, like `if (a = b)`, but certain kinds
of errors are still easier to make in C than in some other languages.

bart

unread,
Feb 9, 2024, 1:02:50 PMFeb 9
to
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

unread,
Feb 9, 2024, 1:04:55 PMFeb 9
to
On 09/02/2024 17:38, Kaz Kylheku wrote:
> On 2024-02-09, Keith Thompson <Keith.S.T...@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.

Keith Thompson

unread,
Feb 9, 2024, 1:28:25 PMFeb 9
to
bart <b...@freeuk.com> writes:
> On 09/02/2024 17:38, Kaz Kylheku wrote:
>> On 2024-02-09, Keith Thompson <Keith.S.T...@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?
>

It doesn't know. If you enable the warning (-Wparentheses, enabled by
-Wall), it assumes that an assignment at the top level of a condition
was probably meant to be a comparison, and warns about it. The warning
suggests adding parentheses, so `if ((a = b))` avoids the warning.

> Simply warning on the possibility is not going to be helpful, because
> you will be swamped with output that may hide more important matters.

Assignments in conditions are rare enough that you're not likely to be
swamped.

fir

unread,
Feb 9, 2024, 1:46:36 PMFeb 9
to
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

Kaz Kylheku

unread,
Feb 9, 2024, 1:52:49 PMFeb 9
to
On 2024-02-09, bart <b...@freeuk.com> wrote:
> On 09/02/2024 17:38, Kaz Kylheku wrote:
>> On 2024-02-09, Keith Thompson <Keith.S.T...@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?

The point is that this is not knowable; it is ambiguous. (Perhaps
the current maintainer of the code doesn't even know).

That's why it deserves a diagnostic.

Someone will have to look at it and figure out whether it should
be the 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.

So you might suspect, but that turns out to be wrong.

GCC assumes that this is a mistake and warns about it, suggesting
that parentheses be put around the assignment if it is intended.

warning: suggest parentheses around assignment used as truth value
[-Wparentheses]

This -Wparentheses is included in -Wall. Thus:

if (a = b) // warns

if ((a = b)) // shuts up

this heuristic turns out to be good. The diagnostic rarely occurs in the
first place, and the fix is trivial.

Parentheses normally disambiguate associativity/precedence. So by a kind
of metaphor, here they are used to fix a psychological rather than
grammatical ambiguity.

David Brown

unread,
Feb 9, 2024, 2:20:56 PMFeb 9
to
On 09/02/2024 18:09, Keith Thompson wrote:
> David Brown <david...@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 can also happen accidentally - even experienced programmers can make
typos which they don't spot immediately. But experienced programmers
will normally be using tools that will find such mistakes very quickly.


>
> 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".
>

Yes.

Blue-Maned_Hawk

unread,
Feb 9, 2024, 2:47:59 PMFeb 9
to
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”.



--
Blue-Maned_Hawk│shortens to
Hawk│/
blu.mɛin.dʰak/
│he/him/his/himself/Mr.
blue-maned_hawk.srht.site
It cost 53 million pounds just to cancel.

fir

unread,
Feb 9, 2024, 3:49:17 PMFeb 9
to
in fact i could conclude:

a=b assigment should be something that resembles "=" but in the
direction of <- or something like that
a==b comparsion should be something that resembles "=" but in the
direction of something like comparsion sign

bioth obviously should be one sign..in asci there is no way to resolve
that i guess

i guess even = could be for comparsion but yopu would need another =
more in direction like <- (but not quite) for assigments

in asci that cont be done properly (i think)
in asci you only can have some aproximation of this, and i probably
would hold a=b for assigment and use a?=b for comparison (but only as
approximation and use unicode for full 'version')

Keith Thompson

unread,
Feb 9, 2024, 4:11:31 PMFeb 9
to
Keith Thompson <Keith.S.T...@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.

Lawrence D'Oliveiro

unread,
Feb 9, 2024, 4:31:32 PMFeb 9
to
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) ...

fir

unread,
Feb 9, 2024, 5:11:37 PMFeb 9
to
Keith Thompson wrote:
> Keith Thompson <Keith.S.T...@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.
>


it io not in the spirit of c (and c design intentions) SO
people like you or the guy who want to consider to remove
assigments in expressions dont understand c
(i understand it at least better, question is if fully)

Kaz Kylheku

unread,
Feb 9, 2024, 5:14:33 PMFeb 9
to
On 2024-02-09, Keith Thompson <Keith.S.T...@gmail.com> wrote:
> Keith Thompson <Keith.S.T...@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).

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.

Ben Bacarisse

unread,
Feb 9, 2024, 5:41:18 PMFeb 9
to
Yes, it's a good summary of what passes for "common knowledge". But I
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?

--
Ben.

Ben Bacarisse

unread,
Feb 9, 2024, 5:43:21 PMFeb 9
to
David Brown <david...@hesbynett.no> writes:

> On 09/02/2024 11:16, Ben Bacarisse wrote:
>> David Brown <david...@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 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.

--
Ben.

Malcolm McLean

unread,
Feb 9, 2024, 6:54:18 PMFeb 9
to
I did have an example recently in my own code recently (shipped,
commercial, tested, supposedly bug free code). There was an assignment
in a if expression which somehow slipped through. But it's only one
example.

Lawrence D'Oliveiro

unread,
Feb 9, 2024, 9:37:44 PMFeb 9
to
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”.

Kaz Kylheku

unread,
Feb 9, 2024, 10:07:01 PMFeb 9
to
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.

Keith Thompson

unread,
Feb 9, 2024, 11:16:58 PMFeb 9
to
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.

Keith Thompson

unread,
Feb 9, 2024, 11:18:04 PMFeb 9
to
Keith Thompson <Keith.S.T...@gmail.com> writes:
> Lawrence D'Oliveiro <l...@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

Blue-Maned_Hawk

unread,
Feb 10, 2024, 3:06:07 AMFeb 10
to
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.



--
Blue-Maned_Hawk│shortens to
Hawk│/
blu.mɛin.dʰak/
│he/him/his/himself/Mr.
blue-maned_hawk.srht.site
LOCAL MAN'S SPEECH ENTIRELY INCONSEQUENTIAL

Ben Bacarisse

unread,
Feb 10, 2024, 8:03:35 AMFeb 10
to
Malcolm McLean <malcolm.ar...@gmail.com> writes:

> On 09/02/2024 22:41, Ben Bacarisse wrote:
...
>> Yes, it's a good summary of what passes for "common knowledge". But I
>> 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?
>>
> I did have an example recently in my own code recently (shipped,
> commercial, tested, supposedly bug free code). There was an assignment in a
> if expression which somehow slipped through. But it's only one
> example.

Can you post a link to the post? I know you've switch readers, so it
may not be obvious how to do that, but I'd appreciate it.

--
Ben.

Ben Bacarisse

unread,
Feb 10, 2024, 8:06:33 AMFeb 10
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:

Oddly worded. They can't mean what they say.

--
Ben.

David Brown

unread,
Feb 10, 2024, 8:42:42 AMFeb 10
to
That would be interesting, yes. It sounds like a good task for a
postgraduate student thesis.


David Brown

unread,
Feb 10, 2024, 9:02:46 AMFeb 10
to
On 10/02/2024 04:06, Kaz Kylheku wrote:
> On 2024-02-10, Lawrence D'Oliveiro <l...@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.
>

The MISRA rules are a mixed bag. Some of them are definitely things
that should be considered obvious - such as "don't rely on the results
of undefined behaviour". And some are also more appropriate for people
using poorer tools (or who don't know how to use their tools well).
Some are directly unhelpful - it talks about an "effective type" system
that is, as I recall, subtly wrong.

It is worth remembering the target audience, especially for older
versions of MISRA (their rules have been updated several times). It
used to be the norm that compilers for microcontrollers were a bit odd -
they could be very poor at optimising (leading to people doing dangerous
tricks, or at least unclear code, to get faster results), and poor at
warnings. They often had lots of extensions, and non-conforming
features. (I've seen an 8-bit sort-of-C compiler that intentionally
does not promote 8-bit types to "int" as required - and that was a big
name, big price toolchain.) These tools also change slowly - many did
not have decent C99 support until perhaps fifteen years ago, so you
couldn't use the newer and better C version. And the tools can have
more bugs than more popular toolchains with wider audiences.

A fair proportion of people programming for small embedded systems are
primarily electronics engineers and other hardware people that have
moved into software. They often lack significant formal education in
programming or in C. So guidelines here can match that.

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.

Tim Rentsch

unread,
Feb 10, 2024, 10:31:51 AMFeb 10
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:

> 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!

What code would you write to accomplish the same thing, under the
assumption that what you're proposing is adopted?

As long as I'm asking, how would you write it in C as it is now?

David Brown

unread,
Feb 10, 2024, 10:54:01 AMFeb 10
to
On 10/02/2024 05:17, Keith Thompson wrote:
> Keith Thompson <Keith.S.T...@gmail.com> writes:
>> Lawrence D'Oliveiro <l...@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.
>

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.

(And in MISRA 2012 there is the extraordinary, messy, vague and badly
defined idea of "the essential type model" which seems to be what the
MISRA authors wished C had for its types, operators and conversions, but
which is at odds with what C really has.)


In MISRA C 2012, the assignment rule is simpler : "The result of an
assignment operator should not be used".


David Brown

unread,
Feb 10, 2024, 10:58:16 AMFeb 10
to
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

unread,
Feb 10, 2024, 11:07:01 AMFeb 10
to
On 10/02/2024 09:05, Blue-Maned_Hawk 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.
>

I have seen them all over the place. They are very common in code
written to MISRA, even though they are not required by the standard. It
is also common in code written by people who have been taught that C is
"dangerous" and you need to write "safe" C like :

if (42 == x) ...

or

if (TRUE == (x < y)) ...

(I'm not making this up.)


Lawrence D'Oliveiro

unread,
Feb 10, 2024, 4:46:38 PMFeb 10
to
On Sat, 10 Feb 2024 15:02:30 +0100, David Brown wrote:

> 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.

Nevertheless, they are based on real-world experience with certain all-
too-common errors with C programming, are they not.

Lawrence D'Oliveiro

unread,
Feb 10, 2024, 4:48:21 PMFeb 10
to
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.

Lawrence D'Oliveiro

unread,
Feb 10, 2024, 4:49:47 PMFeb 10
to
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?

Python manages to allow these, without allowing assignments to actually
have a value as such.

Of course, Python has its own pitfalls, such as

a = b = []

Ben Bacarisse

unread,
Feb 10, 2024, 5:45:17 PMFeb 10
to
David Brown <david...@hesbynett.no> writes:

> On 10/02/2024 14:06, Ben Bacarisse wrote:
>> Lawrence D'Oliveiro <l...@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.
>
> 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.

--
Ben.

Ben Bacarisse

unread,
Feb 10, 2024, 5:47:14 PMFeb 10
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:

> On Sat, 10 Feb 2024 13:06:13 +0000, Ben Bacarisse wrote:
>
>> Lawrence D'Oliveiro <l...@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.

See my (corrected) reply to David Brown for why their examples make it
clear that they don't mean what they say.

--
Ben.

Ben Bacarisse

unread,
Feb 10, 2024, 5:49:39 PMFeb 10
to
Ben Bacarisse <ben.u...@bsb.me.uk> writes:

> David Brown <david...@hesbynett.no> writes:
>
>> On 10/02/2024 14:06, Ben Bacarisse wrote:
>>> Lawrence D'Oliveiro <l...@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.
>>
>> 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.

I need to correct this because (though I am guessing) they probably mean
that the value of the assignment can't be used in the integer-valued
expression whose operator is !=.

Keith Thompson

unread,
Feb 10, 2024, 6:59:08 PMFeb 10
to
I'm fairly sure that what they intended to say was that any expression
used as a condition shall not include an assignment operator. It reads
like they couldn't think of the word "condition" and worked around it by
redefining "boolean" (and never telling anyone what it really means).

And apparently a later edition strengthened and simplified the rule to
ban any use of the result of an assignment.

bart

unread,
Feb 10, 2024, 7:11:35 PMFeb 10
to
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!

Lawrence D'Oliveiro

unread,
Feb 10, 2024, 7:15:38 PMFeb 10
to
On Sat, 10 Feb 2024 22:45:01 +0000, Ben Bacarisse wrote:

> or maybe use break:
>
> while (1) {
> x = get_the_next_x(...);
> if (x != NO_MORE_Xs) break;
> ... use x ...
> }

This is the best approach, though in C I generally use “for (;;)” to
indicate “loop forever”. The nice thing is it gracefully generalizes to
more code before (and after) the break, and multiple exits from the loop.

Lawrence D'Oliveiro

unread,
Feb 10, 2024, 7:17:26 PMFeb 10
to
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.

Ben Bacarisse

unread,
Feb 10, 2024, 8:09:12 PMFeb 10
to
Lawrence D'Oliveiro <l...@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? If so you could have written

a = b = 1;

and made the same claim.

> But this point is moot, since the later revision disallows assignment
> chaining completely, anyway.

--
Ben.

Lawrence D'Oliveiro

unread,
Feb 10, 2024, 8:18:55 PMFeb 10
to
On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:

> Lawrence D'Oliveiro <l...@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.

Keith Thompson

unread,
Feb 10, 2024, 8:35:05 PMFeb 10
to
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

unread,
Feb 10, 2024, 8:42:28 PMFeb 10
to
On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:

> Lawrence D'Oliveiro <l...@nz.invalid> writes:
>
>> On Sun, 11 Feb 2024 01:08:51 +0000, Ben Bacarisse wrote:
>>
>>> Lawrence D'Oliveiro <l...@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.

All just new, different names for what I said: still the only kind of
“boolean” C has.

Keith Thompson

unread,
Feb 10, 2024, 9:01:12 PMFeb 10
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:
> On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
>> Lawrence D'Oliveiro <l...@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".

Lawrence D'Oliveiro

unread,
Feb 11, 2024, 12:30:46 AMFeb 11
to
On Sat, 10 Feb 2024 18:00:57 -0800, Keith Thompson wrote:

> Lawrence D'Oliveiro <l...@nz.invalid> writes:
>> On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
>>> Lawrence D'Oliveiro <l...@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.

No, it is not:

>>> But the equality and relational operators still yield results of type
>>> int with value 0 or 1.

See, no “distinct boolean type”.

Keith Thompson

unread,
Feb 11, 2024, 12:37:42 AMFeb 11
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:
> On Sat, 10 Feb 2024 18:00:57 -0800, Keith Thompson wrote:
>> Lawrence D'Oliveiro <l...@nz.invalid> writes:
>>> On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
>>>> Lawrence D'Oliveiro <l...@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.
>
> No, it is not:

Incorrect.

>>>> But the equality and relational operators still yield results of type
>>>> int with value 0 or 1.

Yes, and?

> See, no “distinct boolean type”.

I see. You're simply wrong.

_Bool is a distinct type. Equality and relational operators yield
results of type int, which is not type _Bool.

Again, C has a distinct boolean type *that it doesn't use in some
contexts where it would make sense to do so, for historical reasons*.

Which part of that do you disagree with?

Malcolm McLean

unread,
Feb 11, 2024, 5:46:19 AMFeb 11
to
Now is my memory playing tricks on me?

I hae a distinct memory of taking out that bug recently. But all the
changes are kept in git repositories. I've checked the repositories, and
that bug is nowhere to be seen.
--
Check out Basic Algorithms and my other books:
https://www.lulu.com/spotlight/bgy1mm

fir

unread,
Feb 11, 2024, 6:09:31 AMFeb 11
to
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

unread,
Feb 11, 2024, 6:24:04 AMFeb 11
to
in fact i also think that more then one sign for asigments is needed

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

unread,
Feb 11, 2024, 6:38:04 AMFeb 11
to
the decision just to open up unicode can simplify things

for exampel i was wondering back than herdly if

a b c = d e f

should be a 3 element 'vector' or 5 element vector..decision to take
unicode just allow to take one = for 1-element scalar assigment
and soem other sign resembling = for n-element vector assigment
..without it there is some more hard way i probably will even not explore

(and i probably resolved the trouble of what to do with comma "'"

a b, c d e, f

comam should be separator something liek ";" today
those "tuples" separated by space should be vectors, or
particles/particules as i neme them

im presently not sure if some suitable 2-element particules not reserve
for assigments liek

x 1, y 2

means x=1, y=2 but x 1 2 or foo x 1 are 3-element vectors, but im not
sure if this will not break something as it "przeslania" (forget an
englis word, covers?) the 2-element vector syntax i maybe would need


hovever this pure vectors laying in white emptiness of context
of much nothing maybe are worth to cover by something more usable

as some could say this context is wasted







fir

unread,
Feb 11, 2024, 6:46:41 AMFeb 11
to
optional is not bed also clever editir sein such particles could
set output variables as one color input as another and bold teh function
call name

David Brown

unread,
Feb 11, 2024, 7:37:01 AMFeb 11
to
On 10/02/2024 22:49, Lawrence D'Oliveiro wrote:
> 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?
>

Correct.

Chained assignments are used in three ways, I would say :

1. Inappropriately grouping things that are logically separate :

index = sum = 0;

Splitting these makes code clearer.

2. Grouping things to save lines using old-style "declare variables at
the top of the function" code:

int a, b;
...
a = b = 0;

Rather write:

int a = 0;
int b = 0;

3. Cases where grouping really does make sense :

x = y = z = initial_value;


I don't see a problem with case 3, but these are so rare that it is not
a problem if a coding style disallows them.




David Brown

unread,
Feb 11, 2024, 7:45:36 AMFeb 11
to
On 10/02/2024 23:45, Ben Bacarisse wrote:
> David Brown <david...@hesbynett.no> writes:
>
>> On 10/02/2024 14:06, Ben Bacarisse wrote:
>>> Lawrence D'Oliveiro <l...@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.
>>
>> 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.
>

To be clear - I am quoting MISRA here, not saying I think it is
necessarily a good idea, or that the MISRA standards explain it well.

(They don't mean "_Bool" here, because that was MISRA 1998, which
considered only C90.)

> 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.

Agreed.

> 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.
>

That's the issue with almost any rule - there are almost always cases
where breaking the rule leads to clearer code (possibly clearer simply
because it is idiomatic, and therefore familiar).


David Brown

unread,
Feb 11, 2024, 7:50:50 AMFeb 11
to
MISRA disallows extensions, despite most compilers used by people
writing MISRA code /requiring/ extensions to do the job.

MISRA 1998 starts with these rules :

1. All code shall conform to ISO 9899 standard C, with no extensions
permitted.

2. Code written in languages other than C should only be used if
there is a defined interface standard for object code to which the
compilers/assemblers for both languages conform.

3. Assembly language functions that are called from C should be
written as C functions containing only in-line assembly language,
and in-line assembly language should not be embedded in normal
C code.

So you are only allowed to use C for your code, conforming to standard
C90, without extensions. But you are allowed to use code in other
languages. And you can't use extensions for your compiler, but if you
use assembly functions, they must be in C inline assembly - which
necessitates extensions.

Did I mention that I thought MISRA was a bit mixed up?




David Brown

unread,
Feb 11, 2024, 7:53:05 AMFeb 11
to
On 11/02/2024 02:08, Ben Bacarisse wrote:
> Lawrence D'Oliveiro <l...@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?

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.)



David Brown

unread,
Feb 11, 2024, 7:57:37 AMFeb 11
to
No. It was badly worded. They had been trying to rule out "if (x = y)"
and requiring it to be written "x = y; if (x != 0) ...".

They did not intend to allow chained assignments - they simply didn't
think to rule them out in MISRA 1998. In MISRA 2012, they changed that
to explicitly rule out /any/ use of the value of an assignment expression.


You are attributing a level of sophistication and forethought to the
MISRA authors that they simply did not have.


Malcolm McLean

unread,
Feb 11, 2024, 11:55:34 AMFeb 11
to
On 11/02/2024 02:00, Keith Thompson wrote:
> Lawrence D'Oliveiro <l...@nz.invalid> writes:
>> On Sat, 10 Feb 2024 17:34:51 -0800, Keith Thompson wrote:
>>> Lawrence D'Oliveiro <l...@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".
>
Other lanaguages were designed with a "boolean" type which had 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.
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.

David Brown

unread,
Feb 11, 2024, 12:05:29 PMFeb 11
to
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 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.


Richard Kettlewell

unread,
Feb 11, 2024, 12:21:41 PMFeb 11
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:
> 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.

Possibly you’re suggesting that with hindsight, C should have always
worked like that. If it had been then we’d have fewer bugs and the
status quo bias would mean little or no pressure to allow assignment
expressions in a wider set of contexts.

Alternatively, you’re suggesting it as a future change. That leads to a
couple of questions. First are you envisaging it as a new rule in a
future version of standard C, or a new language which differs from C in
this one detail (call it C prime, perhaps)? The second is how you
envisage it being deployed, given the huge body of code that depends
(wisely or not) on the existing rules, and would need to be modified to
follow the new rules without any change to its meaning.

--
https://www.greenend.org.uk/rjk/

Malcolm McLean

unread,
Feb 11, 2024, 1:00:28 PMFeb 11
to
So in fact it should be pretty obvious what LDO is getting at.

>> 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.
>
I used to say "bool breaks libraries" and this is exactly the problem. 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.

Thiago Adams

unread,
Feb 11, 2024, 2:12:46 PMFeb 11
to
Em 2/8/2024 9:39 PM, Lawrence D'Oliveiro escreveu:
> 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.

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.

So

if (a == b) ...

would emit an warning.

To deal with this problem I have two "types" in expressions.

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"

void f(bool b);
f(2); //I have a warning
f(2 == 2); //but not here

I want to make an exception for pointer

if (pointer) ...

because this is very common.

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.

In this case...
if (a = b) is naturally an warning except if a and b are booleans but
even in this case I may add an warning.







Thiago Adams

unread,
Feb 11, 2024, 2:15:41 PMFeb 11
to
Em 2/11/2024 4:12 PM, Thiago Adams escreveu:
> Em 2/8/2024 9:39 PM, Lawrence D'Oliveiro escreveu:
>> 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.
>
> 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.
>
> So
>
> if (a == b) ...
>
> would emit an warning.
>
> To deal with this problem I have two "types" in expressions.


forgot to include literal char.
The type of 'A' is int.. however the second type is "character"

This is to allow extra checks.

Keith Thompson

unread,
Feb 11, 2024, 4:15:33 PMFeb 11
to
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*.

Lawrence D'Oliveiro

unread,
Feb 11, 2024, 8:13:56 PMFeb 11
to
On Sun, 11 Feb 2024 16:12:25 -0300, Thiago Adams wrote:

> 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.

But boolean is a subtype of int anyway, so what’s the harm in redefining
conditional expressions to return bool instead?

> 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"

If bool is a subtype of (unsigned?) int, then you are allowed to pass bool
where int is wanted, but not the other way round.

> 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.

Again, enums can be considered to be subtypes of int (or even unsigned
int). You can think of bool as a special case of a predefined enum.

Lawrence D'Oliveiro

unread,
Feb 11, 2024, 8:14:34 PMFeb 11
to
On Sun, 11 Feb 2024 13:57:23 +0100, David Brown wrote:

> You are attributing a level of sophistication and forethought to the
> MISRA authors that they simply did not have.

Fair enough. ;)

Lawrence D'Oliveiro

unread,
Feb 11, 2024, 8:16:26 PMFeb 11
to
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.

Lawrence D'Oliveiro

unread,
Feb 11, 2024, 8:17:57 PMFeb 11
to
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.

Keith Thompson

unread,
Feb 11, 2024, 10:09:19 PMFeb 11
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:
> On Sun, 11 Feb 2024 16:12:25 -0300, Thiago Adams wrote:
>
>> 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.
>
> But boolean is a subtype of int anyway, so what’s the harm in redefining
> conditional expressions to return bool instead?

No, boolean (by which I presume you mean _Bool / bool) is not a
"subtype" of int. C doesn't have anything called "subtypes". _Bool and
int are distinct types, just as short and int are distinct types.

>> 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"
>
> If bool is a subtype of (unsigned?) int, then you are allowed to pass bool
> where int is wanted, but not the other way round.

I don't know what you mean by "subtype". There are implicit conversions
in both directions between _Bool and int, which apply to assignment,
parameter passing, etc. Conversions to _Bool can lose information.

>> 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.
>
> Again, enums can be considered to be subtypes of int (or even unsigned
> int). You can think of bool as a special case of a predefined enum.

No, enum types are also distinct types, and bool is not an enum type
(though it has some resemblance to enum types). (Enumerators are of
type int.)

Keith Thompson

unread,
Feb 11, 2024, 10:12:53 PMFeb 11
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:
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?

Keith Thompson

unread,
Feb 11, 2024, 10:34:56 PMFeb 11
to
Keith Thompson <Keith.S.T...@gmail.com> writes:
> Lawrence D'Oliveiro <l...@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.

Lawrence D'Oliveiro

unread,
Feb 11, 2024, 10:48:11 PMFeb 11
to
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.

Keith Thompson

unread,
Feb 11, 2024, 11:12:48 PMFeb 11
to
Lawrence D'Oliveiro <l...@nz.invalid> writes:
Correct. int, short int, and _Bool are three distinct and incompatible
types.

David Brown

unread,
Feb 12, 2024, 6:23:49 AMFeb 12
to
These are indeed distinct and incompatible types. That applies even if
they happen to be the same size.

Do you know what "incompatible types" are, and what they mean? Do you
realise that they cannot be swapped around as you suggest?

As an example, look at the code generated for this with gcc for the
msp430 (a 16-bit target, where "int" and "short int" are the same size,
and where the assembly is simple enough to understand).

<https://godbolt.org/z/81cE5YThz>

int sizeof_short = sizeof(short int);
int sizeof_int = sizeof(int);

int foo1(int * p, short int * q) {
*p = 10;
*q += 1;
return *p;
}

int foo2(int * p, int * q) {
*p = 10;
*q += 1;
return *p;
}


foo1:
MOV.W #10, @R12
ADD.W #1, @R13
MOV.B #10, R12
RET
foo2:
MOV.W #10, @R12
ADD.W #1, @R13
MOV.W @R12, R12
RET
sizeof_int:
.short 2
sizeof_short:
.short 2



The compiler knows that in "foo1", "p" and "q" cannot point to the same
thing, because they are incompatible types. For "foo2", when swapping
"short int" for "int", the code is less efficient - it needs an extra
read from memory.

David Brown

unread,
Feb 12, 2024, 6:26:46 AMFeb 12
to
On 12/02/2024 04:34, Keith Thompson wrote:
> Keith Thompson <Keith.S.T...@gmail.com> writes:
>> Lawrence D'Oliveiro <l...@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;


bart

unread,
Feb 12, 2024, 6:38:29 AMFeb 12
to
I assume the * is a typo?

David Brown

unread,
Feb 12, 2024, 6:40:39 AMFeb 12
to
I agree - it is fairly obvious what he means. It is equally obvious
that he is wrong.

>
>>> 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.
>>
> I used to say "bool breaks libraries" and this is exactly the problem.

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.




David Brown

unread,
Feb 12, 2024, 6:42:26 AMFeb 12
to
No, I don't seem to be saying that at all. An "int" value can
implicitly be converted to a _Bool.

That does not mean that "int" and "_Bool" are the same thing.

David Brown

unread,
Feb 12, 2024, 6:49:19 AMFeb 12
to
On 11/02/2024 22:15, Keith Thompson wrote:
> David Brown <david...@hesbynett.no> writes:
>> On 11/02/2024 02:08, Ben Bacarisse wrote:
>>> Lawrence D'Oliveiro <l...@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?
>>
>> 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".

Correct - the term "essentially boolean" is from MISRA 2012, while the
rule you quote there is from MISRA 1998. There are several versions of
MISRA C (1998, 2004, 2012, 2016, and 2023) - I have been referring to
1998 and 2012, since these are the versions I have available. (I should
probably buy a copy of the latest version some time.)

The "essential type" system is in MISRA 2012, but not MISRA 1998. (I
don't know about 2004.)

I would say that MISRA 1998 should also define the term "Boolean value",
but it does not.

>
> 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*.
>

I think you are searching for consistency and meaning where there is
none to be found. IMHO the standard is vague and woolly about this kind
of thing, and it is extremely simple to think of examples that don't fit
neatly with their rules.

MISRA 2012 is bad, but less bad than MISRA 1998. Perhaps by MISRA 2023
(which is the third revision of MISRA 2012), they've done better.


David Brown

unread,
Feb 12, 2024, 8:36:17 AMFeb 12
to
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.)


bart

unread,
Feb 12, 2024, 8:57:49 AMFeb 12
to
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

unread,
Feb 12, 2024, 10:04:57 AMFeb 12
to
On 12/02/2024 14:57, bart wrote:
> 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.
>

Conversions of a pointer to "int" or to "_Bool" are both allowed by the
C standards. So a conforming C compiler has to accept them and generate
appropriate code for them.

If the pointer's value cannot be represented in the target type when
converting to an integer type, then it is undefined behaviour - but the
compiler usually can't know that for sure at compile time. Thus it has
to generate code that accepts this and will work if the address happens
to be small enough. The compiler can, however, issue a warning that the
programmer is probably doing something silly.

Conversion of any scaler (including pointers) to _Bool is done by
comparison to 0. And since that is often a sensible thing to do, there
is no warning in gcc - it would give too many false positives.

>>
>> 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.
>

You really should remove it, or fix it. Having a type that is called
_Bool but does not act like _Bool is likely to be confusing and unhelpful.

The key properties of _Bool are :

1. It is a standard /unsigned/ integer type, big enough to hold 0 or 1.

2. Conversion of any scaler to _Bool is done by comparison to 0, not by
truncation, and it can only ever have a value of 0 or 1. (The padding
bits can have any value.)

Since assignment is done by conversion, that also means that something
like "_Bool b = 2;" is implemented as "_Bool b = (2 != 0);", thus
setting "b" to 1.

> (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.)
>

I would recommend that your _Bool in C works as required by the C99
standards, or is removed entirely. I know you are not aiming for any
kind of strict conformance, but it's still not a good idea to have such
inconsistencies.


Keith Thompson

unread,
Feb 12, 2024, 11:14:04 AMFeb 12
to
David Brown <david...@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:
>>>> 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?
>
> 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.

[...]

Keith Thompson

unread,
Feb 12, 2024, 11:20:57 AMFeb 12
to
David Brown <david...@hesbynett.no> writes:
[...]
>>>> On 12/02/2024 11:26, David Brown wrote:
[...]
>>>>>      int * p;
[...]
>>>>>      _Bool b = p;
[...]
>>>>>      int x = p;
[...]
> Conversions of a pointer to "int" or to "_Bool" are both allowed by
> the C standards. So a conforming C compiler has to accept them and
> generate appropriate code for them.
>
> If the pointer's value cannot be represented in the target type when
> converting to an integer type, then it is undefined behaviour - but
> the compiler usually can't know that for sure at compile time. Thus
> it has to generate code that accepts this and will work if the address
> happens to be small enough. The compiler can, however, issue a
> warning that the programmer is probably doing something silly.
>
> Conversion of any scaler (including pointers) to _Bool is done by
> comparison to 0. And since that is often a sensible thing to do,
> there is no warning in gcc - it would give too many false positives.

Conversion of a pointer to int behaves as you describe, but cannot be
done implicitly. A cast is required to avoid a constraint violation.
It is loading more messages.
0 new messages