Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

God is subtle, but he is not malicious. -- Albert Einstein


devel / comp.lang.c / Corrupted C99 _Bool?

SubjectAuthor
* Corrupted C99 _Bool?das...@gmail.com
+* Re: Corrupted C99 _Bool?Keith Thompson
|+- Re: Corrupted C99 _Bool?Keith Thompson
|+- Re: Corrupted C99 _Bool?James Kuyper
|`* Re: Corrupted C99 _Bool?Tim Rentsch
| `* Re: Corrupted C99 _Bool?Keith Thompson
|  `- Re: Corrupted C99 _Bool?Tim Rentsch
+- Re: Corrupted C99 _Bool?David Brown
`* Re: Corrupted C99 _Bool?Opus
 +* Re: Corrupted C99 _Bool?Keith Thompson
 |`- Re: Corrupted C99 _Bool?Tim Rentsch
 +* Re: Corrupted C99 _Bool?James Kuyper
 |`* Re: Corrupted C99 _Bool?das...@gmail.com
 | +- Re: Corrupted C99 _Bool?Ben Bacarisse
 | +- Re: Corrupted C99 _Bool?Keith Thompson
 | `* Re: Corrupted C99 _Bool?David Brown
 |  `* Re: Corrupted C99 _Bool?Keith Thompson
 |   +- Re: Corrupted C99 _Bool?David Brown
 |   `- Re: Corrupted C99 _Bool?Chris M. Thomasson
 `- Re: Corrupted C99 _Bool?Tim Rentsch

1
Corrupted C99 _Bool?

<2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26085&group=comp.lang.c#26085

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a05:622a:1a85:b0:403:3bc1:54e7 with SMTP id s5-20020a05622a1a8500b004033bc154e7mr70587qtc.12.1689121954414;
Tue, 11 Jul 2023 17:32:34 -0700 (PDT)
X-Received: by 2002:a05:6214:1841:b0:635:ddbc:cfc7 with SMTP id
d1-20020a056214184100b00635ddbccfc7mr69534qvy.1.1689121954208; Tue, 11 Jul
2023 17:32:34 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Tue, 11 Jul 2023 17:32:33 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=68.42.82.255; posting-account=_fjjBwoAAACf5uWL0FWgR46LXP5X2qYB
NNTP-Posting-Host: 68.42.82.255
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
Subject: Corrupted C99 _Bool?
From: dash...@gmail.com (das...@gmail.com)
Injection-Date: Wed, 12 Jul 2023 00:32:34 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 1729
 by: das...@gmail.com - Wed, 12 Jul 2023 00:32 UTC

C99 indicates that a _Bool is an unsigned integer type. When a variable of a type other than _Bool is assigned to a _Bool, C99 specifies that the _Bool receives the value of 0 if the variable was 0, or 1 otherwise.

But what does C99 say about a _Bool that is corrupted to a value other than 0 or 1 (perhaps through a pointer error in another part of the program)? Will this corrupted _Bool still function correctly?

For example:

_Bool a = true;
_Bool b; /* Assume b is corrupted to "2" somehow */

if (a && b)
{ /* Would the compiler be able to use a bitwise */
/* AND above, because it assumes all _Bools */
/* must be 0 or 1, so that if (1 && 2) becomes */
/* if (1 & 2) and evaluates false? */
}

Thanks for any clarification.

Re: Corrupted C99 _Bool?

<87edldq4lr.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26086&group=comp.lang.c#26086

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Tue, 11 Jul 2023 18:51:44 -0700
Organization: None to speak of
Lines: 36
Message-ID: <87edldq4lr.fsf@nosuchdomain.example.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="512cad37119bf1d9d63750bcbb75de11";
logging-data="3341174"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+Zvm4VY5VUB5XJ+u0cWGWa"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:rtEsBiAfvma0MP65MKWgx+ioO9I=
sha1:kWzhKtAaai0/yxa7Qwg/dznqWOs=
 by: Keith Thompson - Wed, 12 Jul 2023 01:51 UTC

"das...@gmail.com" <dashley@gmail.com> writes:
> C99 indicates that a _Bool is an unsigned integer type. When a
> variable of a type other than _Bool is assigned to a _Bool, C99
> specifies that the _Bool receives the value of 0 if the variable was
> 0, or 1 otherwise.
>
> But what does C99 say about a _Bool that is corrupted to a value other
> than 0 or 1 (perhaps through a pointer error in another part of the
> program)? Will this corrupted _Bool still function correctly?
>
> For example:
>
> _Bool a = true;
> _Bool b; /* Assume b is corrupted to "2" somehow */
>
> if (a && b)
> {
> /* Would the compiler be able to use a bitwise */
> /* AND above, because it assumes all _Bools */
> /* must be 0 or 1, so that if (1 && 2) becomes */
> /* if (1 & 2) and evaluates false? */
> }
>
> Thanks for any clarification.

I'm reasonably sure that anything that would cause a _Bool object to
have a value other than 0 or 1, or at least anything that tried to
access such an object's value, would have undefined behavior.

Using bitwise AND for the code above is one of the infinitely many
things a compiler could do.

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Re: Corrupted C99 _Bool?

<87a5w1q3ks.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26087&group=comp.lang.c#26087

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Tue, 11 Jul 2023 19:13:55 -0700
Organization: None to speak of
Lines: 43
Message-ID: <87a5w1q3ks.fsf@nosuchdomain.example.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<87edldq4lr.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="512cad37119bf1d9d63750bcbb75de11";
logging-data="3346220"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18XFtPhRCQAz7Ytx2sbAjRh"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:vX/oSYLrPazj6u51b9njF/y2eD4=
sha1:4myUT99mU5UPnkAdjyCFGOvg2bo=
 by: Keith Thompson - Wed, 12 Jul 2023 02:13 UTC

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> "das...@gmail.com" <dashley@gmail.com> writes:
>> C99 indicates that a _Bool is an unsigned integer type. When a
>> variable of a type other than _Bool is assigned to a _Bool, C99
>> specifies that the _Bool receives the value of 0 if the variable was
>> 0, or 1 otherwise.
>>
>> But what does C99 say about a _Bool that is corrupted to a value other
>> than 0 or 1 (perhaps through a pointer error in another part of the
>> program)? Will this corrupted _Bool still function correctly?
>>
>> For example:
>>
>> _Bool a = true;
>> _Bool b; /* Assume b is corrupted to "2" somehow */
>>
>> if (a && b)
>> {
>> /* Would the compiler be able to use a bitwise */
>> /* AND above, because it assumes all _Bools */
>> /* must be 0 or 1, so that if (1 && 2) becomes */
>> /* if (1 & 2) and evaluates false? */
>> }
>>
>> Thanks for any clarification.
>
> I'm reasonably sure that anything that would cause a _Bool object to
> have a value other than 0 or 1, or at least anything that tried to
> access such an object's value, would have undefined behavior.
>
> Using bitwise AND for the code above is one of the infinitely many
> things a compiler could do.

And C23 (see the N3096 public draft) clarifies that bool has one value
bit (sizeof(bool)*CHAR_BIT)-1 padding bits. (bool is a keyword in C23;
_Bool and <stdbool.h> are kept for backward compatibility.)

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Re: Corrupted C99 _Bool?

<u8liab$37e1n$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26088&group=comp.lang.c#26088

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: jameskuy...@alumni.caltech.edu (James Kuyper)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Wed, 12 Jul 2023 02:47:38 -0400
Organization: A noiseless patient Spider
Lines: 34
Message-ID: <u8liab$37e1n$1@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<87edldq4lr.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 12 Jul 2023 06:47:39 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="714ee5dbc68ebd6637c02553b095bc06";
logging-data="3389495"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/VueDLxLXyJx5YF+LK06QUsbcGr4q3J4c="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.11.0
Cancel-Lock: sha1:jWn1BdRi5eDK3RvvWdHRNg/asYg=
Content-Language: en-US
In-Reply-To: <87edldq4lr.fsf@nosuchdomain.example.com>
 by: James Kuyper - Wed, 12 Jul 2023 06:47 UTC

On 7/11/23 21:51, Keith Thompson wrote:
> "das...@gmail.com" <dashley@gmail.com> writes:
>> C99 indicates that a _Bool is an unsigned integer type. When a
>> variable of a type other than _Bool is assigned to a _Bool, C99
>> specifies that the _Bool receives the value of 0 if the variable was
>> 0, or 1 otherwise.
>>
>> But what does C99 say about a _Bool that is corrupted to a value other
>> than 0 or 1 (perhaps through a pointer error in another part of the
>> program)? Will this corrupted _Bool still function correctly?
>>
>> For example:
>>
>> _Bool a = true;
>> _Bool b; /* Assume b is corrupted to "2" somehow */
>>
>> if (a && b)
>> {
>> /* Would the compiler be able to use a bitwise */
>> /* AND above, because it assumes all _Bools */
>> /* must be 0 or 1, so that if (1 && 2) becomes */
>> /* if (1 & 2) and evaluates false? */
>> }
>>
>> Thanks for any clarification.
>
> I'm reasonably sure that anything that would cause a _Bool object to
> have a value other than 0 or 1, or at least anything that tried to
> access such an object's value, would have undefined behavior.

You know this, but the OP might not realize it: one of the (infinitely
many) permitted consequence of the fact that your code has undefined
behavior is that an object with a type of _Bool might, when accessed,
have a result (such as 2) that is not one a valid _Bool value.

Re: Corrupted C99 _Bool?

<u8lks5$37n2l$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26089&group=comp.lang.c#26089

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Wed, 12 Jul 2023 09:31:17 +0200
Organization: A noiseless patient Spider
Lines: 84
Message-ID: <u8lks5$37n2l$1@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 12 Jul 2023 07:31:17 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="4565391ae6d0f1364adc1e6f962f5781";
logging-data="3398741"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+kQsroafbAAS98fiCoeTOImI9AmbsJKWk="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.9.0
Cancel-Lock: sha1:r8ltnop9r93hp3qZsf+T0779tYw=
In-Reply-To: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
Content-Language: en-GB
 by: David Brown - Wed, 12 Jul 2023 07:31 UTC

On 12/07/2023 02:32, das...@gmail.com wrote:
> C99 indicates that a _Bool is an unsigned integer type. When a
> variable of a type other than _Bool is assigned to a _Bool, C99
> specifies that the _Bool receives the value of 0 if the variable was 0,
> or 1 otherwise.
>
> But what does C99 say about a _Bool that is corrupted to a value
> other
> than 0 or 1 (perhaps through a pointer error in another part of the
> program)? Will this corrupted _Bool still function correctly?
>
> For example:
>
> _Bool a = true;
> _Bool b; /* Assume b is corrupted to "2" somehow */
>
> if (a && b)
> {
> /* Would the compiler be able to use a bitwise */
> /* AND above, because it assumes all _Bools */
> /* must be 0 or 1, so that if (1 && 2) becomes */
> /* if (1 & 2) and evaluates false? */
> }
>
> Thanks for any clarification.

You have absolutely no guarantees - it is all "undefined behaviour". If
you make a _Bool with a value other than 0 or 1 (say, by using memcpy()
or a char* pointer to access it), any attempt to use it will be undefined.

This means the compiler can, and will, assume that any _Bool expression
will be 0 or 1. It can implement the "if (a && b)" expression any way
it likes that is consistent with that assumption. So given _Bool "a"
and "b", the compiler can implement "if (a && b) ..." as :

if (a) {
if (b) ...
}

or

if (b) {
if (a == 0) {} else { ... }
}

or

if (a + b == 2) ...

or

if (a & b) ...

or

if (a * b) ...

or

if (a << 1 | b == 3) ...

There really is no limit to how this could be implemented.

You can also get effects like :

if (a) { doThis(); } else { doThat(); }

resulting in /both/ doThis() and doThat() being executed, or perhaps
neither of them, if "a" is a corrupted _Bool.

(I remember debugging a program where there was an accidental _Bool
corruption, leading to exactly this kind of effect. It was seriously
confusing!)

When you use _Bool, you promise your compiler that you will never break
the languages rules and ask it to handle a _Bool with a value other than
0 or 1. Don't lie to your compiler - it always ends in tears!

Re: Corrupted C99 _Bool?

<u8n1cg$3cc3o$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26100&group=comp.lang.c#26100

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ifo...@youknew.org (Opus)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Wed, 12 Jul 2023 22:10:55 +0200
Organization: A noiseless patient Spider
Lines: 65
Message-ID: <u8n1cg$3cc3o$2@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 12 Jul 2023 20:10:56 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="ca000bc6bd6990e0563d1bed4a241498";
logging-data="3551352"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19gSly4HTci7xibWxTtYkPm"
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.13.0
Cancel-Lock: sha1:DZ5iad9Muuw2Gd714sk1SqGARd8=
In-Reply-To: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
Content-Language: en-US
 by: Opus - Wed, 12 Jul 2023 20:10 UTC

On 12/07/2023 02:32, das...@gmail.com wrote:
> C99 indicates that a _Bool is an unsigned integer type. When a variable of a type other than _Bool is assigned to a _Bool, C99 specifies that the _Bool receives the value of 0 if the variable was 0, or 1 otherwise.
>
> But what does C99 say about a _Bool that is corrupted to a value other than 0 or 1 (perhaps through a pointer error in another part of the program)? Will this corrupted _Bool still function correctly?
>

It's undefined behavior. Just like if you corrupt any value of any other
type.

> For example:
>
> _Bool a = true;
> _Bool b; /* Assume b is corrupted to "2" somehow */
>
> if (a && b)
> {
> /* Would the compiler be able to use a bitwise */
> /* AND above, because it assumes all _Bools */
> /* must be 0 or 1, so that if (1 && 2) becomes */
> /* if (1 & 2) and evaluates false? */
> }
>
> Thanks for any clarification.

If the memory holding a _Bool value gets corrupted, there is obviously
no way for the compiler to automatically correct it. How would it?

It's UB, but the practical result will of course depend on the target. A
_Bool is held by an integer under the hood in practice.

Compilers do force a value of 1 for any value other than 0 assigned to
it *during assignment*, and 0 otherwise. But again, only when an
assignment occurs (or a cast).

For instance, the expression '(int)(_Bool) 5' yields 1.

But if you alias a _Bool, say:

_Bool b;

*(int *) &b = 5;

While UB, in practice in most implementations, b will be represented
internally as an int and here will hold the value 5. Not 1.
This would cause a problem if you expect the value to be either 0 or 1
exclusively. For instance if you cast it back to an int and do some
artihmetic or bitwise operations with that.

Regarding what would happen to '(a && b)' in your example, the '&&'
operator is NOT a bitwise operator. Even when dealing strictly with
_Bool's on each side of the operator, it can't be implemented with a
bitwise operation when compiled. Quoting the standard regarding the '&&'
operator:

"The && operator shall yield 1 if both of its operands compare unequal
to 0; otherwise, it yields 0. The result has type int.
Unlike the bitwise binary & operator, the && operator guarantees left
to-right evaluation;
if the second operand is evaluated, there is a sequence point between
the evaluations of the first and second operands. If the first operand
compares equal to 0, the second operand is not evaluated."

That should answer your question.

Re: Corrupted C99 _Bool?

<875y6oq10u.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26101&group=comp.lang.c#26101

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Wed, 12 Jul 2023 14:21:21 -0700
Organization: None to speak of
Lines: 89
Message-ID: <875y6oq10u.fsf@nosuchdomain.example.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="512cad37119bf1d9d63750bcbb75de11";
logging-data="3566155"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/OJJIeXThqNhy40S8Zo4YZ"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:qExZlU43m4VS7pVYoqFrqC9LdMc=
sha1:DYM5LqJjUASVKEr5ziAhIV2V7QE=
 by: Keith Thompson - Wed, 12 Jul 2023 21:21 UTC

Opus <ifonly@youknew.org> writes:

> On 12/07/2023 02:32, das...@gmail.com wrote:
>> C99 indicates that a _Bool is an unsigned integer type. When a
>> variable of a type other than _Bool is assigned to a _Bool, C99
>> specifies that the _Bool receives the value of 0 if the variable was
>> 0, or 1 otherwise.
>> But what does C99 say about a _Bool that is corrupted to a value
>> other than 0 or 1 (perhaps through a pointer error in another part
>> of the program)? Will this corrupted _Bool still function
>> correctly?
>>
>
> It's undefined behavior. Just like if you corrupt any value of any
> other type.
>
>> For example:
>> _Bool a = true;
>> _Bool b; /* Assume b is corrupted to "2" somehow */
>> if (a && b)
>> {
>> /* Would the compiler be able to use a bitwise */
>> /* AND above, because it assumes all _Bools */
>> /* must be 0 or 1, so that if (1 && 2) becomes */
>> /* if (1 & 2) and evaluates false? */
>> }
>> Thanks for any clarification.
>
> If the memory holding a _Bool value gets corrupted, there is obviously
> no way for the compiler to automatically correct it. How would it?
>
> It's UB, but the practical result will of course depend on the
> target. A _Bool is held by an integer under the hood in practice.
>
> Compilers do force a value of 1 for any value other than 0 assigned to
> it *during assignment*, and 0 otherwise. But again, only when an
> assignment occurs (or a cast).

More precisely, *conversion* from any scalar type to _Bool yields a
value of 0 if the converted value is 0, 1 otherwise. Assignment
performs an implicit conversion; so do argument passing, initialization,
and a return statement. And of course a cast performs an explicit
conversion.

> For instance, the expression '(int)(_Bool) 5' yields 1.
>
> But if you alias a _Bool, say:
>
> _Bool b;
>
> *(int *) &b = 5;
>
> While UB, in practice in most implementations, b will be represented
> internally as an int and here will hold the value 5. Not 1.

_Bool is most likely smaller than int, so the assignment is likely to
clobber bytes not belonging to the _Bool object.

> This would cause a problem if you expect the value to be either 0 or 1
> exclusively. For instance if you cast it back to an int and do some
> artihmetic or bitwise operations with that.
>
> Regarding what would happen to '(a && b)' in your example, the '&&'
> operator is NOT a bitwise operator. Even when dealing strictly with
> _Bool's on each side of the operator, it can't be implemented with a
> bitwise operation when compiled. Quoting the standard regarding the
> '&&' operator:
>
> "The && operator shall yield 1 if both of its operands compare unequal
> to 0; otherwise, it yields 0. The result has type int.
> Unlike the bitwise binary & operator, the && operator guarantees left
> to-right evaluation;
> if the second operand is evaluated, there is a sequence point between
> the evaluations of the first and second operands. If the first operand
> compares equal to 0, the second operand is not evaluated."

Yes, but if a and b are both of type _Bool, the compiler can assume that
they both have a value of 0 or 1. If that assumption is valid (and if a
and b are not volatile), then `a & b` and `a && b` yield the same value.
If the assumption is not valid, then the behavior of `a && b` is
undefined.

A compiler *can* implement `a && b` as `a & b` if both are of type _Bool
and neither is volatile.

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Re: Corrupted C99 _Bool?

<u8nad4$3d9tu$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26102&group=comp.lang.c#26102

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: jameskuy...@alumni.caltech.edu (James Kuyper)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Wed, 12 Jul 2023 18:44:52 -0400
Organization: A noiseless patient Spider
Lines: 38
Message-ID: <u8nad4$3d9tu$1@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 12 Jul 2023 22:44:52 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="81e40980e3742e5a88e5da0dbfd3cded";
logging-data="3581886"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/7Q2AjPtZyKWidNSzWQKjNnZmbKadm9yk="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.13.0
Cancel-Lock: sha1:nSmU9G/RCvV5iZhyl2Dppse4YdE=
In-Reply-To: <u8n1cg$3cc3o$2@dont-email.me>
Content-Language: en-US
 by: James Kuyper - Wed, 12 Jul 2023 22:44 UTC

On 7/12/23 16:10, Opus wrote:
> On 12/07/2023 02:32, das...@gmail.com wrote:
>> C99 indicates that a _Bool is an unsigned integer type. When a
>> variable of a type other than _Bool is assigned to a _Bool, C99
>> specifies that the _Bool receives the value of 0 if the variable was
>> 0, or 1 otherwise.
>>
>> But what does C99 say about a _Bool that is corrupted to a value
>> other than 0 or 1 (perhaps through a pointer error in another part of
>> the program)? Will this corrupted _Bool still function correctly?
>>
>
> It's undefined behavior. Just like if you corrupt any value of any
> other type.

Not quite. The unsigned size-named types are prohibited from having
padding bits, and have requirements on the different possible values
that they can represent that guarantee that every possible bit pattern
represents a valid value. As a result, placing an arbitrary bit pattern
in an object of one of those types, if done by a method that has in
itself no undefined behavior, has no worse consequence than to leave the
value represented unspecified - it must still be a valid value of that type.

....
> If the memory holding a _Bool value gets corrupted, there is obviously
> no way for the compiler to automatically correct it. How would it?

An implementation could generate code for every access through an lvalue
of type _Bool that is equivalent to retrieving an integer value from
that location and then doing the equivalent of !!val, or val&1, or any
other operation that maps 0 to 0 and 1 to 1, and maps every valid
integer value to one of those two values.

Implementations are not required to do that, which is what makes such
code dangerous. However, they are permitted to that, which is what would
make is possible for the code to be safe with a particular implementation.

Re: Corrupted C99 _Bool?

<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26103&group=comp.lang.c#26103

  copy link   Newsgroups: comp.lang.c
X-Received: by 2002:a05:620a:4042:b0:767:404c:787f with SMTP id i2-20020a05620a404200b00767404c787fmr81901qko.3.1689205264174;
Wed, 12 Jul 2023 16:41:04 -0700 (PDT)
X-Received: by 2002:a9d:6d07:0:b0:6b9:5bfc:9b33 with SMTP id
o7-20020a9d6d07000000b006b95bfc9b33mr63241otp.6.1689205263972; Wed, 12 Jul
2023 16:41:03 -0700 (PDT)
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.c
Date: Wed, 12 Jul 2023 16:41:03 -0700 (PDT)
In-Reply-To: <u8nad4$3d9tu$1@dont-email.me>
Injection-Info: google-groups.googlegroups.com; posting-host=68.42.82.255; posting-account=_fjjBwoAAACf5uWL0FWgR46LXP5X2qYB
NNTP-Posting-Host: 68.42.82.255
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
Subject: Re: Corrupted C99 _Bool?
From: dash...@gmail.com (das...@gmail.com)
Injection-Date: Wed, 12 Jul 2023 23:41:04 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
 by: das...@gmail.com - Wed, 12 Jul 2023 23:41 UTC

On Wednesday, July 12, 2023 at 6:45:06 PM UTC-4, James Kuyper wrote:
> An implementation could generate code for every access through an lvalue
> of type _Bool that is equivalent to retrieving an integer value from
> that location and then doing the equivalent of !!val, or val&1, or any
> other operation that maps 0 to 0 and 1 to 1, and maps every valid
> integer value to one of those two values.
>
> Implementations are not required to do that, which is what makes such
> code dangerous. However, they are permitted to that, which is what would
> make is possible for the code to be safe with a particular implementation..

Thanks for the informative replies. Opus' interpretation comes the closest to how I read the C99 standard,
but James Kuyper's reply comes closest to how I think about the problem (as mapping).

I often see code like this:

typedef unsigned char boolean;
boolean a = FALSE;
boolean b = TRUE;
a = 42; //Oops, some other part of the program used an uninitialized pointer.
if ((a == FALSE) && (b == TRUE)) ...

The problem I have with the tests against FALSE and TRUE is that there are 254 values that are neither FALSE nor TRUE. This is an "equivalence classing" or "mapping" problem. Every possible bit pattern has to behave as if it is FALSE or TRUE.

One solution is this: if (!a && b) ...

Another solution is: if ((a == FALSE) && (b != FALSE)) ...

So, back to my original post ...

SOUGHT GUARANTEE: I'm only looking for one guarantee: for a given improper (corrupted) value of a _Bool on a given platform, it will always test as if it is logically false or logically true. In other words, the compiler can't use methods that would result in a value of 42 testing as false in one place and true in another. This is ultimately a mapping or equivalence-classing requirement. All bit patterns would have to map to false or true.

Do I have this guarantee?

And the followup question would be, in the event of corruption, what happens if you do any of these things?

if (a == b) ...
if (a == false) ...
if (a == true) ...

Re: Corrupted C99 _Bool?

<87a5w0k6kp.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26104&group=comp.lang.c#26104

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Thu, 13 Jul 2023 01:17:58 +0100
Organization: A noiseless patient Spider
Lines: 109
Message-ID: <87a5w0k6kp.fsf@bsb.me.uk>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Injection-Info: dont-email.me; posting-host="49e0f6e41ab1811fe4b2a5f30d7c6202";
logging-data="3597519"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+RCrLL96df1V8ZpJMzquPZXTFW9ula7YM="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:MFYAnu53nqiRL4rXYiCJ09vGpHQ=
sha1:9XKnD3MdWUzjUOakk5vDvG0KqSQ=
X-BSB-Auth: 1.c0c84192400e4cde6f2a.20230713011758BST.87a5w0k6kp.fsf@bsb.me.uk
 by: Ben Bacarisse - Thu, 13 Jul 2023 00:17 UTC

"das...@gmail.com" <dashley@gmail.com> writes:

> On Wednesday, July 12, 2023 at 6:45:06 PM UTC-4, James Kuyper wrote:
>> An implementation could generate code for every access through an lvalue
>> of type _Bool that is equivalent to retrieving an integer value from
>> that location and then doing the equivalent of !!val, or val&1, or any
>> other operation that maps 0 to 0 and 1 to 1, and maps every valid
>> integer value to one of those two values.
>>
>> Implementations are not required to do that, which is what makes such
>> code dangerous. However, they are permitted to that, which is what would
>> make is possible for the code to be safe with a particular implementation.
>
> Thanks for the informative replies. Opus' interpretation comes the
> closest to how I read the C99 standard, but James Kuyper's reply comes
> closest to how I think about the problem (as mapping).
>
> I often see code like this:
>
> typedef unsigned char boolean;
> boolean a = FALSE;
> boolean b = TRUE;
> a = 42; //Oops, some other part of the program used an uninitialized pointer.
> if ((a == FALSE) && (b == TRUE)) ...
>
> The problem I have with the tests against FALSE and TRUE is that there
> are 254 values that are neither FALSE nor TRUE. This is an
> "equivalence classing" or "mapping" problem. Every possible bit
> pattern has to behave as if it is FALSE or TRUE.
>
> One solution is this: if (!a && b) ...

Yes. This is how you were supposed to do it before _Bool came along.
Is it not possible to correct the code? Seeing x == TRUE is a huge
red-flag for me. I'd want it fixed as soon as possible.

> Another solution is: if ((a == FALSE) && (b != FALSE)) ...
>
> So, back to my original post ...
>
> SOUGHT GUARANTEE: I'm only looking for one guarantee: for a given
> improper (corrupted) value of a _Bool on a given platform, it will
> always test as if it is logically false or logically true.

The language does not give you this guarantee. Any access to a
"corrupt" _Bool object is undefined. The language gives an
implementation permission to do what it likes in such cases.

Of course, an implementation of C could choose to fix exactly what
happens in these cases, but then you are relying on a promise that might
be withdrawn at the next release.

> In other words, the compiler can't use methods that would result in a
> value of 42 testing as false in one place and true in another. This
> is ultimately a mapping or equivalence-classing requirement. All bit
> patterns would have to map to false or true.
>
> Do I have this guarantee?

Ironically you do have this guarantee for typedef unsigned char boolean
objects -- provided the accesses are in the right sort of context --
because there are no padding bits in unsigned char objects. For

unsigned char a, b;

code like

if (a && !b) ...

is always well-defined and "Boolean-like". For example a || b is always
0 or 1.

So switching to _Bool gives you more problem. The very access is
undefined.

Mind you, going "up a level" in your issues, unless the corruption
occurs in a very specific way, the program's behaviour is already
undefined even when using unsigned char.

> And the followup question would be, in the event of corruption, what
> happens if you do any of these things?
>
> if (a == b) ...
> if (a == false) ...
> if (a == true) ...

All formally undefined if a or b is a _Bool object. All formally
defined (though maybe not meaning what was intended) if a and b are
unsigned char.

You can get some help from some compilers. For example:

$ cat b.c
#include <stdio.h>

int main(void)
{ union { _Bool b; char c; } both;
both.c = 42;
printf("%d\n", both.b);
} $ gcc -o b -fsanitize=undefined b.c
$ ./b
b.c:7:25: runtime error: load of value 42, which is not a valid value
for type '_Bool'
0

--
Ben.

Re: Corrupted C99 _Bool?

<87wmz4odsx.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26105&group=comp.lang.c#26105

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Wed, 12 Jul 2023 17:28:14 -0700
Organization: None to speak of
Lines: 97
Message-ID: <87wmz4odsx.fsf@nosuchdomain.example.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Injection-Info: dont-email.me; posting-host="2b19e42c760835ee102e4ee4d867eda6";
logging-data="3599049"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18sL3Rknmxj62jsYM89GE0x"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:4tsPoBMVfRAsC/MWm5tdvTBj+A8=
sha1:bGSiXLL7M4qrkFSeRY2KMQb0KoY=
 by: Keith Thompson - Thu, 13 Jul 2023 00:28 UTC

"das...@gmail.com" <dashley@gmail.com> writes:
> On Wednesday, July 12, 2023 at 6:45:06 PM UTC-4, James Kuyper wrote:
>> An implementation could generate code for every access through an lvalue
>> of type _Bool that is equivalent to retrieving an integer value from
>> that location and then doing the equivalent of !!val, or val&1, or any
>> other operation that maps 0 to 0 and 1 to 1, and maps every valid
>> integer value to one of those two values.
>>
>> Implementations are not required to do that, which is what makes such
>> code dangerous. However, they are permitted to that, which is what would
>> make is possible for the code to be safe with a particular implementation.
>
> Thanks for the informative replies. Opus' interpretation comes the
> closest to how I read the C99 standard, but James Kuyper's reply comes
> closest to how I think about the problem (as mapping).
>
> I often see code like this:
>
> typedef unsigned char boolean;
> boolean a = FALSE;
> boolean b = TRUE;
> a = 42; //Oops, some other part of the program used an uninitialized pointer.
> if ((a == FALSE) && (b == TRUE)) ...
>
> The problem I have with the tests against FALSE and TRUE is that there
> are 254 values that are neither FALSE nor TRUE. This is an
> "equivalence classing" or "mapping" problem. Every possible bit
> pattern has to behave as if it is FALSE or TRUE.

Presumably FALSE and TRUE are #defined as 0 and 1, respectively.

This "boolean" type is not _Bool. It has (typically) 8 value bits and
256 distinct values, all equally valid.

Like any scalar type, if you use a value of this type as a condition,
it's treated as false if it compares equal to 0, true otherise.

It's common in pre-1999 C to use some integer type (char, unsigned
char, int) as a logically boolean type. You have to be aware that
the compiler doesn't assign any meaning to the fact that you named it
"boolean".

I use _Bool if at all possible, but if I can't assume it's available, I
like:

typedef enum { false, true } bool;

But again, an object of this enumerated type has at least 256 distinct
values, and I need to avoid assigning values other than false or true.

One option is to carefully write your code so that no value other than 0
or 1 is ever stored in an object of your pseudo-boolean type -- but
that's very ndifficult to do consistently, and the compiler will not
warn you if you make a mistake.

A better option is to avoid using any operations that care which
non-zero value an object of your type has. *Never* compiler a logically
boolean value for equality or inequality to FALSE or TRUE. Don't write
`if (a == FALSE && b == TRUE)`; write `if (!a && b)`.

> One solution is this: if (!a && b) ...
>
> Another solution is: if ((a == FALSE) && (b != FALSE)) ...

It happens that comparison to FALSE is safer than comparison to TRUE,
but the comparison is unnecessary clutter.

> So, back to my original post ...
>
> SOUGHT GUARANTEE: I'm only looking for one guarantee: for a given
> improper (corrupted) value of a _Bool on a given platform, it will
> always test as if it is logically false or logically true. In other
> words, the compiler can't use methods that would result in a value of
> 42 testing as false in one place and true in another. This is
> ultimately a mapping or equivalence-classing requirement. All bit
> patterns would have to map to false or true.
>
> Do I have this guarantee?

No, you absolutely do not have this guarantee. If you've managed to
store a value other than 0 or 1 in a _Bool object, any use of that value
has undefined behavior. Just don't.

> And the followup question would be, in the event of corruption, what
> happens if you do any of these things?
>
> if (a == b) ...
> if (a == false) ...
> if (a == true) ...

Undefined behavior -- and at least for the 2nd and 3rd lines, rejection
in a code review.

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Re: Corrupted C99 _Bool?

<u8og1o$3k7ij$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26108&group=comp.lang.c#26108

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Thu, 13 Jul 2023 11:27:20 +0200
Organization: A noiseless patient Spider
Lines: 165
Message-ID: <u8og1o$3k7ij$1@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Thu, 13 Jul 2023 09:27:20 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="c7d9a2b18210fa23a646e0c3992043bc";
logging-data="3808851"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/FRZmmejLyXC6si8yC1nrhuQlqEFb8/dg="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.9.0
Cancel-Lock: sha1:JHOoFoNS7cll9E2eXhMUioIThTY=
Content-Language: en-GB
In-Reply-To: <59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
 by: David Brown - Thu, 13 Jul 2023 09:27 UTC

On 13/07/2023 01:41, das...@gmail.com wrote:
> On Wednesday, July 12, 2023 at 6:45:06 PM UTC-4, James Kuyper wrote:
>> An implementation could generate code for every access through an lvalue
>> of type _Bool that is equivalent to retrieving an integer value from
>> that location and then doing the equivalent of !!val, or val&1, or any
>> other operation that maps 0 to 0 and 1 to 1, and maps every valid
>> integer value to one of those two values.
>>
>> Implementations are not required to do that, which is what makes such
>> code dangerous. However, they are permitted to that, which is what would
>> make is possible for the code to be safe with a particular implementation.
>
> Thanks for the informative replies. Opus' interpretation comes the closest to how I read the C99 standard,
> but James Kuyper's reply comes closest to how I think about the problem (as mapping).
>

Opus' interpretation was not quite accurate.

The standard does not say anything about the size of _Bool. C23, IIRC,
says it has 1 value bit and the rest of the bits are padding, and its
size must be a multiple of unsigned char. Every implementation I have
seen has sizeof(_Bool) equal to 1 - it is held in a single byte, while
"int" in most implementations (except for some DSPs or other niche
devices) will be multiple bytes.

So while a _Bool is a standard unsigned integer type - it is /not/ an
"int" (or "unsigned int" for that matter).

As others have said, it is better to say that any conversion (allowed by
the language) to _Bool results in a value of 0 or 1, rather than
specifically referring to assignment. The conversion is done exactly as
though you had compared the original value "x" to 0 - if the comparison
is true, the result is 0, otherwise it is 1. It is also equivalent to
writing "!!x", which will result in an int with value 0 or 1.

Opus is also inaccurate about the implementation of &&. It is correct
(and important) to note that in the expression "A && B", "B" is not
evaluated unless "A" compares unequal to 0. But implementations are
free to generate code in all kinds of ways as long as the observable
behaviour of the program is correct. So if evaluating B does not have
any side effects (such as volatile accesses, as Keith mentioned),
implementations can (and do) assume that _Bool "A" and "B" are either 0
or 1, and use bitwise & to implement the logical &&.

> I often see code like this:
>
> typedef unsigned char boolean;

That was common in pre-C99 code. It was also common to use "int" for
such typedefs. Typically there is also:

#define FALSE 0
#define TRUE 1

Sometimes "typedef enum { FALSE, TRUE } boolean;" is used instead.

And occasionally you see horrors such as:

#define TRUE -1
#define FALSE 0

or :

#define TRUE (1 == 1)
#define FALSE (!TRUE)

These are indications that the programmer who wrote them has very little
understanding of the language, and you should treat all the code with
caution and scepticism.

These should never be found in C99 or newer code, except possibly for
interacting with old code.

> boolean a = FALSE;
> boolean b = TRUE;
> a = 42; //Oops, some other part of the program used an uninitialized pointer.
> if ((a == FALSE) && (b == TRUE)) ...
>

Any comparison to FALSE and TRUE like this (or with C99 _Bool,
comparison to false or true) is an indicator that the programmer is not
competent or confident in the language. There /may/ be good reasons for
writing it, but it is usually a warning sign. The evaluation of the
operands to logical &&, and to "if", already contain implicit
comparisons to 0.

Prefer "if (!a && b)". This will be correct for all proper use of
boolean types, including sane pre-C99 definitions. (For the insane
definitions, the code is already a disaster.)

> The problem I have with the tests against FALSE and TRUE is that there are 254 values that are neither FALSE nor TRUE. This is an "equivalence classing" or "mapping" problem. Every possible bit pattern has to behave as if it is FALSE or TRUE.
>

Conversion to _Bool, and conversion to "logical" values (for "if",
"while", &&, ?:, and several other contexts in C) are always done by
comparison to 0. Anything that compares equal to 0, results in 0 (as a
_Bool or an int, depending on context), everything else results in 1.

> One solution is this: if (!a && b) ...

Yes.

>
> Another solution is: if ((a == FALSE) && (b != FALSE)) ...

No. Well, it gives the same result, unlike "b == TRUE" (if "b" is a
"fake boolean rather than a C99 _Bool). But again, it is pointless
redundancy that indicates a limited understanding of the language.

Note that /any/ scaler type can be compared to 0 - that includes
pointers as well as other integer types and floating point types. For
pointers, "if (!a && b)" then reads as "If a is a null pointer and b is
not a null pointer", while "if ((a == FALSE) && (b != FALSE))" reads as
"I am confused and am mixing pointers and booleans".

>
> So, back to my original post ...
>
> SOUGHT GUARANTEE: I'm only looking for one guarantee: for a given improper (corrupted) value of a _Bool on a given platform, it will always test as if it is logically false or logically true. In other words, the compiler can't use methods that would result in a value of 42 testing as false in one place and true in another. This is ultimately a mapping or equivalence-classing requirement. All bit patterns would have to map to false or true.
>
> Do I have this guarantee?

Not with a _Bool, no.

You can read the value via a character type (such as a pointer to
unsigned char), and assign it to a _Bool. Then you get the guarantee.

extern _Bool corrupted_bool;

_Bool b = *(unsigned char*) &corrupted_bool;

But simply writing:

_Bool b = corrupted_bool;

will /not/ give you the guarantee. You can't even write:

_Bool b = !!corrupted_bool;

or

_Bool b = (corrupted_bool == 0) ? 0 : 1;

because the compiler can (and probably will) assume that
"corrupted_bool", being type _Bool, always contains 0 or 1.

>
> And the followup question would be, in the event of corruption, what happens if you do any of these things?
>
> if (a == b) ...
> if (a == false) ...
> if (a == true) ...

Demons may come flying out of your nose. But maybe not - there are no
guarantees when you have undefined behaviour!

Re: Corrupted C99 _Bool?

<87sf9ro3qc.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26119&group=comp.lang.c#26119

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Thu, 13 Jul 2023 15:18:03 -0700
Organization: None to speak of
Lines: 12
Message-ID: <87sf9ro3qc.fsf@nosuchdomain.example.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
<u8og1o$3k7ij$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="ac5a556e1e535137335af0391d9e6d60";
logging-data="3963653"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18o/jehhffFkQMzydiNWpii"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:CBBnWtcxgMvaKgWbplijzCHglq8=
sha1:r/8SX5GTCghTO6nrjahZMZt0i7A=
 by: Keith Thompson - Thu, 13 Jul 2023 22:18 UTC

David Brown <david.brown@hesbynett.no> writes:
[...]
> Sometimes "typedef enum { FALSE, TRUE } boolean;" is used instead.

enum Bool { True, False, FileNotFound };

(Source: https://thedailywtf.com/articles/what_is_truth_0x3f_)

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Re: Corrupted C99 _Bool?

<u8qs73$3v5vc$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26123&group=comp.lang.c#26123

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Fri, 14 Jul 2023 09:07:15 +0200
Organization: A noiseless patient Spider
Lines: 17
Message-ID: <u8qs73$3v5vc$1@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
<u8og1o$3k7ij$1@dont-email.me> <87sf9ro3qc.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 14 Jul 2023 07:07:16 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="b6c45f79885c516f8f214e1c69339975";
logging-data="4167660"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+qA4erfiUpf1OaSEGgFWcF5fRkcF9ueIw="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
Thunderbird/102.9.0
Cancel-Lock: sha1:WwKhpSoyXJOHIu+LMmXbXa3VjZA=
In-Reply-To: <87sf9ro3qc.fsf@nosuchdomain.example.com>
Content-Language: en-GB
 by: David Brown - Fri, 14 Jul 2023 07:07 UTC

On 14/07/2023 00:18, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> Sometimes "typedef enum { FALSE, TRUE } boolean;" is used instead.
>
> enum Bool { True, False, FileNotFound };
>
> (Source: https://thedailywtf.com/articles/what_is_truth_0x3f_)
>

Very nice :-)

Whenever I am pulling out my hair trying to comprehend someone's bad
code, I visit a random page on that site. Then I know the code I am
working on is not as bad as it /could/ be!

Re: Corrupted C99 _Bool?

<u8quu7$3ve51$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26125&group=comp.lang.c#26125

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: chris.m....@gmail.com (Chris M. Thomasson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Fri, 14 Jul 2023 00:53:43 -0700
Organization: A noiseless patient Spider
Lines: 11
Message-ID: <u8quu7$3ve51$2@dont-email.me>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<u8n1cg$3cc3o$2@dont-email.me> <u8nad4$3d9tu$1@dont-email.me>
<59414686-f8fc-40b0-9c13-a8399003a441n@googlegroups.com>
<u8og1o$3k7ij$1@dont-email.me> <87sf9ro3qc.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 14 Jul 2023 07:53:44 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="ecebf3037a2a34229dd57717e7049a8d";
logging-data="4176033"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18baB05vjqAFEL9fHdXr9Zhx/6MLrABS78="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.13.0
Cancel-Lock: sha1:SJVcYN6+YGhEWrqdZYJZ7D3SJ7Y=
In-Reply-To: <87sf9ro3qc.fsf@nosuchdomain.example.com>
Content-Language: en-US
 by: Chris M. Thomasson - Fri, 14 Jul 2023 07:53 UTC

On 7/13/2023 3:18 PM, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> Sometimes "typedef enum { FALSE, TRUE } boolean;" is used instead.
>
> enum Bool { True, False, FileNotFound };
>
> (Source: https://thedailywtf.com/articles/what_is_truth_0x3f_)
>

WOW! Good one. :^D

Re: Corrupted C99 _Bool?

<86351hx553.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26409&group=comp.lang.c#26409

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Thu, 20 Jul 2023 21:25:28 -0700
Organization: A noiseless patient Spider
Lines: 50
Message-ID: <86351hx553.fsf@linuxsc.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com> <87edldq4lr.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="2d78163bfb891e7187c96a580a5a5784";
logging-data="3282444"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/+EXHWqW/s38p5F/o47uDc5DxzICfvIqY="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:T5t14Ilt/WWekakDnWj6+tXwBa0=
sha1:5lclnVqRA5jyYNpxyampSACm/Zs=
 by: Tim Rentsch - Fri, 21 Jul 2023 04:25 UTC

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> "das...@gmail.com" <dashley@gmail.com> writes:
>
>> C99 indicates that a _Bool is an unsigned integer type. When a
>> variable of a type other than _Bool is assigned to a _Bool, C99
>> specifies that the _Bool receives the value of 0 if the variable was
>> 0, or 1 otherwise.
>>
>> But what does C99 say about a _Bool that is corrupted to a value other
>> than 0 or 1 (perhaps through a pointer error in another part of the
>> program)? Will this corrupted _Bool still function correctly?
>>
>> For example:
>>
>> _Bool a = true;
>> _Bool b; /* Assume b is corrupted to "2" somehow */
>>
>> if (a && b)
>> {
>> /* Would the compiler be able to use a bitwise */
>> /* AND above, because it assumes all _Bools */
>> /* must be 0 or 1, so that if (1 && 2) becomes */
>> /* if (1 & 2) and evaluates false? */
>> }
>>
>> Thanks for any clarification.
>
> I'm reasonably sure that anything that would cause a _Bool object
> to have a value other than 0 or 1, or at least anything that tried
> to access such an object's value, would have undefined behavior.

In C99 and also in C11, an implementation may define the type _Bool
to have a size of 1, a width of CHAR_BIT, and a representation that
matches the representation of unsigned char. I'm not aware of any
implementation that makes these choices, but they are allowed under
the rules of the respective ISO C standards (assuming I didn't miss
something, but I'm reasonably sure that I didn't).

Code running in such an implementation can easily store an object
representation, into a _Bool object, of an unsigned char with the
value 2. Because the representations of _Bool and unsigned char
are the same, that is also the object representation of the value 2
considered as a _Bool object.

After the store, reading the _Bool object (as a _Bool) is well
defined, and must produce the value 2, because of how object
representations are turned into values. So, in such an
implementation, 'a && b' might not be the same as 'a & b',
even though no undefined behavior has occurred.

Re: Corrupted C99 _Bool?

<86sf9hvojo.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26410&group=comp.lang.c#26410

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Thu, 20 Jul 2023 22:09:15 -0700
Organization: A noiseless patient Spider
Lines: 20
Message-ID: <86sf9hvojo.fsf@linuxsc.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com> <u8n1cg$3cc3o$2@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="2d78163bfb891e7187c96a580a5a5784";
logging-data="3290646"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18x/F2G5CFJxAS+JtwVKIR05eS1ccRbd8w="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:p2J7leY/5q0+SvDcn8qZydWPDdQ=
sha1:iMBA8cLPj0F13dDFmtJUHcqKPWk=
 by: Tim Rentsch - Fri, 21 Jul 2023 05:09 UTC

Opus <ifonly@youknew.org> writes:

> On 12/07/2023 02:32, das...@gmail.com wrote:
>
>> C99 indicates that a _Bool is an unsigned integer type. When a
>> variable of a type other than _Bool is assigned to a _Bool, C99
>> specifies that the _Bool receives the value of 0 if the variable was
>> 0, or 1 otherwise.
>>
>> But what does C99 say about a _Bool that is corrupted to a value
>> other than 0 or 1 (perhaps through a pointer error in another part of
>> the program)? Will this corrupted _Bool still function correctly?
>
> It's undefined behavior. Just like if you corrupt any value of any
> other type.

More accurately, it might be undefined behavior but doesn't
have to be, depending on what choices have been made by
the implementation. More details in my previous response
to Keith Thompson's earlier posting.

Re: Corrupted C99 _Bool?

<86o7k5vo5c.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26411&group=comp.lang.c#26411

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Thu, 20 Jul 2023 22:17:51 -0700
Organization: A noiseless patient Spider
Lines: 90
Message-ID: <86o7k5vo5c.fsf@linuxsc.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com> <u8n1cg$3cc3o$2@dont-email.me> <875y6oq10u.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="2d78163bfb891e7187c96a580a5a5784";
logging-data="3290646"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18sfTfjGiFlT2gLz9BiYLkYmXCh7J0QbV8="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:MijxG0jB4I/8InBgd7yAN+alGMc=
sha1:pyI7KiRnCeJNtF/tU36fKwTqzlA=
 by: Tim Rentsch - Fri, 21 Jul 2023 05:17 UTC

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Opus <ifonly@youknew.org> writes:
>
>> On 12/07/2023 02:32, das...@gmail.com wrote:
>>
>>> C99 indicates that a _Bool is an unsigned integer type. When a
>>> variable of a type other than _Bool is assigned to a _Bool, C99
>>> specifies that the _Bool receives the value of 0 if the variable was
>>> 0, or 1 otherwise.
>>> But what does C99 say about a _Bool that is corrupted to a value
>>> other than 0 or 1 (perhaps through a pointer error in another part
>>> of the program)? Will this corrupted _Bool still function
>>> correctly?
>>
>> It's undefined behavior. Just like if you corrupt any value of any
>> other type.
>>
>>> For example:
>>> _Bool a = true;
>>> _Bool b; /* Assume b is corrupted to "2" somehow */
>>> if (a && b)
>>> {
>>> /* Would the compiler be able to use a bitwise */
>>> /* AND above, because it assumes all _Bools */
>>> /* must be 0 or 1, so that if (1 && 2) becomes */
>>> /* if (1 & 2) and evaluates false? */
>>> }
>>> Thanks for any clarification.
>>
>> If the memory holding a _Bool value gets corrupted, there is obviously
>> no way for the compiler to automatically correct it. How would it?
>>
>> It's UB, but the practical result will of course depend on the
>> target. A _Bool is held by an integer under the hood in practice.
>>
>> Compilers do force a value of 1 for any value other than 0 assigned to
>> it *during assignment*, and 0 otherwise. But again, only when an
>> assignment occurs (or a cast).
>
> More precisely, *conversion* from any scalar type to _Bool yields a
> value of 0 if the converted value is 0, 1 otherwise. Assignment
> performs an implicit conversion; so do argument passing, initialization,
> and a return statement. And of course a cast performs an explicit
> conversion.
>
>> For instance, the expression '(int)(_Bool) 5' yields 1.
>>
>> But if you alias a _Bool, say:
>>
>> _Bool b;
>>
>> *(int *) &b = 5;
>>
>> While UB, in practice in most implementations, b will be represented
>> internally as an int and here will hold the value 5. Not 1.
>
> _Bool is most likely smaller than int, so the assignment is likely to
> clobber bytes not belonging to the _Bool object.
>
>> This would cause a problem if you expect the value to be either 0 or 1
>> exclusively. For instance if you cast it back to an int and do some
>> artihmetic or bitwise operations with that.
>>
>> Regarding what would happen to '(a && b)' in your example, the '&&'
>> operator is NOT a bitwise operator. Even when dealing strictly with
>> _Bool's on each side of the operator, it can't be implemented with a
>> bitwise operation when compiled. Quoting the standard regarding the
>> '&&' operator:
>>
>> "The && operator shall yield 1 if both of its operands compare unequal
>> to 0; otherwise, it yields 0. The result has type int.
>> Unlike the bitwise binary & operator, the && operator guarantees left
>> to-right evaluation;
>> if the second operand is evaluated, there is a sequence point between
>> the evaluations of the first and second operands. If the first operand
>> compares equal to 0, the second operand is not evaluated."
>
> Yes, but if a and b are both of type _Bool, the compiler can
> assume that they both have a value of 0 or 1. [...]

Whether a compiler can safely make such an assumption depends on
implementation choices pertaining to how _Bool objects are
represented.

> A compiler *can* implement `a && b` as `a & b` if both are of type
> _Bool and neither is volatile.

Again, such a conclusion might or might not be valid, depending on
other aspects of the implementation.

Re: Corrupted C99 _Bool?

<87sf9hprog.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26424&group=comp.lang.c#26424

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Fri, 21 Jul 2023 01:58:07 -0700
Organization: None to speak of
Lines: 88
Message-ID: <87sf9hprog.fsf@nosuchdomain.example.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com>
<87edldq4lr.fsf@nosuchdomain.example.com> <86351hx553.fsf@linuxsc.com>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="2370f913b850030e0527dd0f7396627d";
logging-data="3350787"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/OL3iknKbYyb/BVtCWw8Ha"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:ZRSvKAFYlpur4jvPBB0N3QwEH8k=
sha1:3MPOkICjo+Tb0AxzZFptMIzbNuY=
 by: Keith Thompson - Fri, 21 Jul 2023 08:58 UTC

Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> "das...@gmail.com" <dashley@gmail.com> writes:
>>> C99 indicates that a _Bool is an unsigned integer type. When a
>>> variable of a type other than _Bool is assigned to a _Bool, C99
>>> specifies that the _Bool receives the value of 0 if the variable was
>>> 0, or 1 otherwise.
>>>
>>> But what does C99 say about a _Bool that is corrupted to a value other
>>> than 0 or 1 (perhaps through a pointer error in another part of the
>>> program)? Will this corrupted _Bool still function correctly?
>>>
>>> For example:
>>>
>>> _Bool a = true;
>>> _Bool b; /* Assume b is corrupted to "2" somehow */
>>>
>>> if (a && b)
>>> {
>>> /* Would the compiler be able to use a bitwise */
>>> /* AND above, because it assumes all _Bools */
>>> /* must be 0 or 1, so that if (1 && 2) becomes */
>>> /* if (1 & 2) and evaluates false? */
>>> }
>>>
>>> Thanks for any clarification.
>>
>> I'm reasonably sure that anything that would cause a _Bool object
>> to have a value other than 0 or 1, or at least anything that tried
>> to access such an object's value, would have undefined behavior.
>
> In C99 and also in C11, an implementation may define the type _Bool
> to have a size of 1, a width of CHAR_BIT, and a representation that
> matches the representation of unsigned char. I'm not aware of any
> implementation that makes these choices, but they are allowed under
> the rules of the respective ISO C standards (assuming I didn't miss
> something, but I'm reasonably sure that I didn't).

As far as I can tell, gcc's behavior is consistent with that.

> Code running in such an implementation can easily store an object
> representation, into a _Bool object, of an unsigned char with the
> value 2. Because the representations of _Bool and unsigned char
> are the same, that is also the object representation of the value 2
> considered as a _Bool object.
>
> After the store, reading the _Bool object (as a _Bool) is well
> defined, and must produce the value 2, because of how object
> representations are turned into values. So, in such an
> implementation, 'a && b' might not be the same as 'a & b',
> even though no undefined behavior has occurred.

C23 (as of the N3096 draft) resolves this by saying that:

The type bool shall have one value bit and (sizeof(bool)*CHAR_BIT)-1
padding bits.

which means that if sizeof (bool) == 1 and a bool object's
representation is all-bits-one, the value of that bool object is 1
(true), since the (typically 7) padding bits do not contribute to the
value.

This program:

#include <stdio.h>
#include <string.h>
int main(void) {
unsigned char c = -1;
_Bool b;
memcpy(&b, &c, 1);
printf("sizeof b = %zu, b = %d\n", sizeof b, b);
}

produces this output with gcc:

sizeof b = 1, b = 255

C23 doesn't seem to specify whether the resulting representation of b is
a non-value representation (previously "trap representation") or not.
If a representation with any padding bits set to 1 is a non-value
representation, then I *think* that the code has undefined behavior.
(I'm assuming that compilers aren't expected to go to extra effort when
converting *from* bool.)

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Re: Corrupted C99 _Bool?

<86fs5hufhx.fsf@linuxsc.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=26453&group=comp.lang.c#26453

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: tr.17...@z991.linuxsc.com (Tim Rentsch)
Newsgroups: comp.lang.c
Subject: Re: Corrupted C99 _Bool?
Date: Fri, 21 Jul 2023 14:22:18 -0700
Organization: A noiseless patient Spider
Lines: 121
Message-ID: <86fs5hufhx.fsf@linuxsc.com>
References: <2569e26b-c60a-4873-a759-ee00a50e2bf9n@googlegroups.com> <87edldq4lr.fsf@nosuchdomain.example.com> <86351hx553.fsf@linuxsc.com> <87sf9hprog.fsf@nosuchdomain.example.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: dont-email.me; posting-host="2d78163bfb891e7187c96a580a5a5784";
logging-data="3624840"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX196ERHGUCjG/E+up7msuCbUgid8f2xAx+k="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:YXUd7h+XbOcNWP1oo2IABSYkC0I=
sha1:j5FbF3ci22vx955QV9whNw6IaB8=
 by: Tim Rentsch - Fri, 21 Jul 2023 21:22 UTC

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> "das...@gmail.com" <dashley@gmail.com> writes:
>>>
>>>> C99 indicates that a _Bool is an unsigned integer type. When a
>>>> variable of a type other than _Bool is assigned to a _Bool, C99
>>>> specifies that the _Bool receives the value of 0 if the variable was
>>>> 0, or 1 otherwise.
>>>>
>>>> But what does C99 say about a _Bool that is corrupted to a value other
>>>> than 0 or 1 (perhaps through a pointer error in another part of the
>>>> program)? Will this corrupted _Bool still function correctly?
>>>>
>>>> For example:
>>>>
>>>> _Bool a = true;
>>>> _Bool b; /* Assume b is corrupted to "2" somehow */
>>>>
>>>> if (a && b)
>>>> {
>>>> /* Would the compiler be able to use a bitwise */
>>>> /* AND above, because it assumes all _Bools */
>>>> /* must be 0 or 1, so that if (1 && 2) becomes */
>>>> /* if (1 & 2) and evaluates false? */
>>>> }
>>>>
>>>> Thanks for any clarification.
>>>
>>> I'm reasonably sure that anything that would cause a _Bool object
>>> to have a value other than 0 or 1, or at least anything that tried
>>> to access such an object's value, would have undefined behavior.
>>
>> In C99 and also in C11, an implementation may define the type _Bool
>> to have a size of 1, a width of CHAR_BIT, and a representation that
>> matches the representation of unsigned char. I'm not aware of any
>> implementation that makes these choices, but they are allowed under
>> the rules of the respective ISO C standards (assuming I didn't miss
>> something, but I'm reasonably sure that I didn't).
>
> As far as I can tell, gcc's behavior is consistent with that.

I expect that in fact gcc does not make this set of choices. A
way of testing that is to compile this struct definition

struct test_bool_width {
_Bool b : 8; /* or probably any number > 1 */
};

and see if gcc accepts it. On my test system, gcc gives an
error for any width greater than 1.

>> Code running in such an implementation can easily store an object
>> representation, into a _Bool object, of an unsigned char with the
>> value 2. Because the representations of _Bool and unsigned char
>> are the same, that is also the object representation of the value 2
>> considered as a _Bool object.
>>
>> After the store, reading the _Bool object (as a _Bool) is well
>> defined, and must produce the value 2, because of how object
>> representations are turned into values. So, in such an
>> implementation, 'a && b' might not be the same as 'a & b',
>> even though no undefined behavior has occurred.
>
> C23 (as of the N3096 draft) resolves this by saying that:
>
> The type bool shall have one value bit and (sizeof(bool)*CHAR_BIT)-1
> padding bits.
>
> which means that if sizeof (bool) == 1 and a bool object's
> representation is all-bits-one, the value of that bool object is 1
> (true), since the (typically 7) padding bits do not contribute to the
> value.
>
> This program:
>
> #include <stdio.h>
> #include <string.h>
> int main(void) {
> unsigned char c = -1;
> _Bool b;
> memcpy(&b, &c, 1);
> printf("sizeof b = %zu, b = %d\n", sizeof b, b);
> }
>
> produces this output with gcc:
>
> sizeof b = 1, b = 255

Under C23 rules, this program must have had undefined behavior.
The reason is, if there were no undefined behavior, the _Bool
value of b must be either 0 or 1; it cannot be anything else.
Ergo the padding bit values must have produced a non-value
representation, which accounts for the impossible value 255.

> C23 doesn't seem to specify whether the resulting representation of b is
> a non-value representation (previously "trap representation") or not.
> If a representation with any padding bits set to 1 is a non-value
> representation, then I *think* that the code has undefined behavior.
> (I'm assuming that compilers aren't expected to go to extra effort when
> converting *from* bool.)

The non-zero padding bits /can/ produce a non-value representation,
but they aren't required to. Since the program produced an
impossible value, we know that there must have been undefined
behavior, and thus the non-zero padding bits must have resulted
in a non-value representation (since everything else is well
defined).

Note again that this conclusion is based on the C23 rules. In
earlier versions of C this output is possible (as defined behavior)
if CHAR_BIT == 8 and the width of _Bool is also 8; if the width of
_Bool is anything other than 8 then there must have been undefined
behavior (and as before the width of _Bool can be checked using
the struct bit-field definition method).

Disclaimer: I'm pretty sure all the above is right, but I didn't
re-check my statements as carefully as is my usual practice.

1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor