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.