Path: csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c
Subject: Re: Constants and undefined behavior
Date: Mon, 08 Jun 2026 23:05:24 -0700
Organization: A noiseless patient Spider
Lines: 100
Message-ID: <86tsrc8d0b.fsf@linuxsc.com>
References: <10v7b32$2u85v$1@dont-email.me> <86ik81cfk5.fsf_-_@linuxsc.com> <10vn0bk$ghg$1@reader1.panix.com> <865x3yd21n.fsf@linuxsc.com> <10vs997$rp5$1@reader1.panix.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Tue, 09 Jun 2026 06:05:25 +0000 (UTC)
Injection-Info: dont-email.me; logging-data="3940845"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+OIWE3UoLXMVJ8GOCCUJcf6vk7fXP9gYM="; posting-host="279f363b91f2ad5cb0cf462c32d4b36d"
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:wlBX1XXBB1Zkemn3lntVHn6fox0= sha1:25YtEK6QrlREyxJRy3VvNfvZ6Jc= sha256:PDBUdXQRuJbzi2yucm4awLv/l8fVKVxqWnVBiuEhDrw= sha1:OPtVr5E1fQ66fLC6lZgaDO2Gk9s=
Xref: csiph.com comp.lang.c:399805
cross@spitfire.i.gajendra.net (Dan Cross) writes:
> In article <865x3yd21n.fsf@linuxsc.com>,
> Tim Rentsch wrote:
>
>> cross@spitfire.i.gajendra.net (Dan Cross) writes:
>>
>>> In article <86ik81cfk5.fsf_-_@linuxsc.com>,
>>> Tim Rentsch wrote:
>>>
>>>> Janis Papanagnou writes:
>>>>
>>>>> On 2026-06-01 00:54, Keith Thompson wrote:
>>>>>
>>>>>>> [...]
>>>>>>
>>>>>> Yes, a compiler can reduce (a + b) * 0 to just 0. But it's not
>>>>>> required to do so, and (INT_MAX + 1) * 0 still has undefined
>>>>>> behavior. Undefined behavior is determined by the rules of the
>>>>>> abstract machine *without* any adjustments permitted by the as-if
>>>>>> rule.
>>>>>
>>>>> This is something I really don't get in the actual C-logic...
>>>>>
>>>>> Using constants that can be determined at compile time is UB here,
>>>>> despite the '* 0' mathematically indicating an IMO clear semantics,
>>>>> but using variables is only UB possibly at runtime? [...]
>>>>
>>>> There's an important distinction to make here. Consider this
>>>> program:
>>>>
>>>> #include
>>>>
>>>> int
>>>> foo(){
>>>> int zero = (INT_MAX+1)*0;
>>>> return zero;
>>>> }
>>>>
>>>> int
>>>> main(){
>>>> return 0;
>>>> }
>>>>
>>>> This program does not transgress the bounds of undefined behavior.
>>
>> To clarify, the comments in my posting were meant to be read as
>> saying the given text is the entire program, and that it is strictly
>> conforming with respect to conforming hosted implementations.
>> (Incidentally, given the rules for freestanding implementations, I'm
>> not sure that it is even possible for any program to be strictly
>> conforming with respect to conforming freestanding implementations.
>> In any case my statements were meant only in the context of hosted
>> implementations.)
>
> Ok.
>
>>> [snip]
>>> Perhaps you mean that this is irrelevant because `foo` is not
>>> invoked, but I see no reason why that need be the case in e.g.
>>> a freestanding environment.
>>
>> I explained the context of my previous statements above. Sorry for
>> not saying that in the original message.
>>
>>> In a hosted environment, I don't
>>> think anything explicitly prevents `foo` from being called after
>>> `main` returns (though I can't imagine that would happen in real
>>> life; it would be weird if it did).
>>
>> The semantics described in the ISO C standard don't admit that
>> possibility.
I have read through much of what has been said in the subthread
following this posting. I expect I will not be responding to much
of it; my overall sense is that the discussion is mostly confused.
I would like to say one thing here, and see if that helps things.
> Could you please point to where it says this, in the C standard?
>
> I cannot find anything that says that arbitrary code cannot run
> after `main()` returns, and I don't see how that could possibly
> be true.
The logic here is backwards. The C standard is prescriptive: it
says what _does_ happen, not what _doesn't_ happen. If one wants
to establish that some "action" takes place, it is necessary to
find a passage, or passages, in the C standard that, if all are
taken together, shows that the "action" occurs, or at least that it
can occur. The C standard doesn't need to say that, for example, a
function x() other than main(), whose name is never referenced,
will never be called. If someone wants to establish that x() could
be called, there needs to be a chain of reasoning going through the
semantic descriptions given in the C standard, to show that a call
to x() could occur. If there is no such chain of reasoning, naming
the pertinent passages in the C standard, to establish a possible
call, then there is no possible call. In other words the burden of
proof for a claim that some action could occur rests on whoever is
making the claim; there is no need to look for something in the C
standard that says something cannot occur.