Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #400344 > unrolled thread
| Started by | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| First post | 2026-07-22 01:38 +0200 |
| Last post | 2026-07-23 11:18 +0200 |
| Articles | 20 on this page of 186 — 20 participants |
Back to article view | Back to comp.lang.c
Prioritize Performance over Correctness Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-07-22 01:38 +0200
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-21 17:26 -0700
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-22 01:50 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-21 20:25 -0700
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-22 17:37 +0000
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-22 13:26 -0700
Re: Prioritize Performance over Correctness Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-07-22 07:33 +0200
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-07-22 10:41 +0200
Re: Prioritize Performance over Correctness BGB <cr88192@gmail.com> - 2026-07-22 18:08 -0500
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-07-23 10:31 +0200
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-23 14:31 -0700
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-23 14:48 -0700
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-23 15:11 -0700
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-07-24 09:23 +0200
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-24 03:14 -0700
Re: Prioritize Performance over Correctness scott@slp53.sl.home (Scott Lurndal) - 2026-07-24 14:56 +0000
Re: Prioritize Performance over Correctness antispam@fricas.org (Waldek Hebisch) - 2026-07-25 16:30 +0000
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-27 09:33 -0400
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 00:22 +0800
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-27 12:58 -0700
Re: Prioritize Performance over Correctness BGB <cr88192@gmail.com> - 2026-07-27 15:37 -0500
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-27 17:13 -0400
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-27 15:17 -0700
Re: Prioritize Performance over Correctness scott@slp53.sl.home (Scott Lurndal) - 2026-07-28 01:18 +0000
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 15:40 +0800
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 14:18 +0000
Multics( Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 22:48 +0800
Re: Multics( Re: Prioritize Performance over Correctness) scott@slp53.sl.home (Scott Lurndal) - 2026-07-28 15:08 +0000
Re: Multics( Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 23:30 +0800
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 19:08 +0000
Re: Multics( Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 04:08 +0800
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 22:15 +0000
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 22:26 +0000
Re: Multics( Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 06:41 +0800
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 23:23 +0000
Picture of Organicks' book Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 16:01 +0800
Re: Picture of Organicks' book cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-29 13:46 +0000
Re: Picture of Organicks' book R Kym Horsell <kymhorsell@gmail.com> - 2026-07-29 16:54 +0000
Re: Multics( Re: Prioritize Performance over Correctness) Cóilín Nioclásín Glostéir <thanks-to@Taf.com> - 2026-07-29 23:22 +0000
Re: Multics( Re: Prioritize Performance over Correctness) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 15:55 -0700
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 18:58 +0000
Re: Multics( Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 04:10 +0800
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 22:20 +0000
Re: Multics( Re: Prioritize Performance over Correctness) scott@slp53.sl.home (Scott Lurndal) - 2026-07-29 14:44 +0000
Re: Multics( Re: Prioritize Performance over Correctness) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-30 02:08 +0000
Re: Prioritize Performance over Correctness Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-16 07:59 -0700
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-27 17:59 -0700
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 15:42 +0800
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-28 03:22 -0700
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 19:21 +0800
Re: Prioritize Performance over Correctness bart <bc@freeuk.com> - 2026-07-28 13:02 +0100
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 20:18 +0800
Re: Prioritize Performance over Correctness bart <bc@freeuk.com> - 2026-07-28 14:17 +0100
Re: Prioritize Performance over Correctness BGB <cr88192@gmail.com> - 2026-07-28 16:02 -0500
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 16:45 +0800
Re: Prioritize Performance over Correctness bart <bc@freeuk.com> - 2026-07-29 12:03 +0100
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 19:32 +0800
Re: Prioritize Performance over Correctness bart <bc@freeuk.com> - 2026-07-29 13:42 +0100
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 20:49 +0800
Re: Prioritize Performance over Correctness bart <bc@freeuk.com> - 2026-07-29 16:01 +0100
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-29 12:53 -0700
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-31 14:21 -0400
Re: Prioritize Performance over Correctness bart <bc@freeuk.com> - 2026-07-31 20:07 +0100
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-31 13:00 -0700
Re: Prioritize Correctness Over Performance Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-08-01 02:34 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-28 16:08 -0700
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 23:28 +0000
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 14:22 +0000
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-28 13:51 -0700
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-28 20:32 -0400
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-28 14:20 +0000
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-28 13:54 -0700
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 05:00 +0800
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-28 20:25 -0400
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-29 14:55 -0700
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-28 20:31 -0400
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-28 21:26 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-29 14:57 -0700
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-29 15:33 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-29 16:22 -0700
Re: Prioritize Performance over Correctness Richard Harnden <richard.nospam@gmail.invalid> - 2026-07-30 07:40 +0100
Re: Prioritize Correctness over Performance Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-30 06:48 +0000
Re: Prioritize Correctness over Performance James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-30 06:50 -0400
Re: Prioritize Correctness over Performance Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-30 03:54 -0700
Re: Prioritize Correctness over Performance James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-30 08:24 -0400
Re: Prioritize Correctness over Performance Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-30 14:40 -0700
Re: Prioritize Correctness over Performance "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-30 19:39 -0700
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-30 06:44 -0400
Re: Prioritize Performance over Correctness Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-30 21:00 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-30 14:38 -0700
Re: Prioritize Performance over Correctness Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-30 21:53 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-30 15:10 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-30 19:40 -0700
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-07-31 02:43 +0000
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-30 19:44 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-30 19:58 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-01 01:25 -0700
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-08-02 23:14 +0200
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-02 14:37 -0700
Re: Prioritize Performance over Correctness Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-08-02 22:51 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-02 16:43 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-03 12:03 -0700
Re: Prioritize Correctness Over Performance Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-08-03 23:49 +0000
Re: Prioritize Correctness Over Performance "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-03 19:35 -0700
MS-DOS memory models (was: Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-03 08:08 +0800
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-08-03 10:16 +0200
Re: Prioritize Performance over Correctness Richard Harnden <richard.nospam@gmail.invalid> - 2026-08-03 10:41 +0100
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-08-03 12:28 +0200
Malicious Computer Architecture (was: Re: Prioritize Performance over Correctness) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-03 19:23 +0800
Re: Malicious Computer Architecture David Brown <david.brown@hesbynett.no> - 2026-08-03 14:01 +0200
Re: Malicious Computer Architecture Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-03 22:52 +0800
Re: Malicious Computer Architecture David Brown <david.brown@hesbynett.no> - 2026-08-03 19:41 +0200
Re: Malicious Computer Architecture "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-03 13:13 -0700
Re: Malicious Computer Architecture "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-03 13:10 -0700
Re: Malicious Computer Architecture (was: Re: Prioritize Performance over Correctness) scott@slp53.sl.home (Scott Lurndal) - 2026-08-03 14:29 +0000
Johnny Depp prevention [Windows 11 etc...] (Was: Malicious Computer Architecture) Mild Shock <janburse@fastmail.fm> - 2026-08-03 18:10 +0200
But how can you deploy. when its ROM? (Was: Johnny Depp prevention [Windows 11 etc...]) Mild Shock <janburse@fastmail.fm> - 2026-08-03 18:15 +0200
GPU Elasticity: Collective Communications Libraries (Was: But how can you deploy. when its ROM?) Mild Shock <janburse@fastmail.fm> - 2026-08-07 14:37 +0200
What are Flits and Phits? [Network on a Chip] (Re: GPU Elasticity: Collective Communications Libraries) Mild Shock <janburse@fastmail.fm> - 2026-08-07 18:07 +0200
Cristallina: Thank you for the Beam (Re: What are Flits and Phits? [Network on a Chip]) Mild Shock <janburse@fastmail.fm> - 2026-08-09 21:22 +0200
Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Mild Shock <janburse@fastmail.fm> - 2026-08-18 16:26 +0200
How to shoot yourself in the foot (Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Mild Shock <janburse@fastmail.fm> - 2026-08-18 16:50 +0200
Re: How to shoot yourself in the foot (Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-19 03:24 +0800
Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-19 03:21 +0800
Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Aidan Kehoe <kehoea@parhasard.net> - 2026-08-18 21:13 +0100
Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-08-18 22:49 +0000
Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-19 08:32 +0800
Re: Loderunner Enemy AI better than SWI-Prolog? [Prolog Education Group] Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-19 08:27 +0800
The Mac Neo is a Budget Monster [GPU Channels] (Re: What are Flits and Phits? [Network on a Chip]) Mild Shock <janburse@fastmail.fm> - 2026-08-11 16:27 +0200
The luminaries of duct-tape engineering [Sweeney and Torvald] (Was: The Mac Neo is a Budget Monster [GPU Channels]) Mild Shock <janburse@fastmail.fm> - 2026-08-11 16:51 +0200
Re: Malicious Computer Architecture Aidan Kehoe <kehoea@parhasard.net> - 2026-08-03 19:51 +0100
Re: Malicious Computer Architecture Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-05 00:22 +0800
Re: Malicious Computer Architecture Richard Harnden <richard.nospam@gmail.invalid> - 2026-08-04 19:10 +0100
Re: Malicious Computer Architecture Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-05 03:21 +0800
Re: Malicious Computer Architecture Kaz Kylheku <046-301-5902@kylheku.com> - 2026-08-06 21:55 +0000
Re: Malicious Computer Architecture Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-07 06:31 +0800
Re: Malicious Computer Architecture Aidan Kehoe <kehoea@parhasard.net> - 2026-08-06 23:01 +0100
A Case for Impurity: The Applied Pi Calculus (Re: Malicious Computer Architecture) Mild Shock <janburse@fastmail.fm> - 2026-08-04 14:58 +0200
The Sandcastle of Paul Taraus Interactors (Re: A Case for Impurity: The Applied Pi Calculus) Mild Shock <janburse@fastmail.fm> - 2026-08-04 15:10 +0200
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-03 05:34 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-03 13:04 -0700
Re: Prioritize Correctness Over Performance Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-08-04 00:52 +0000
Re: Prioritize Correctness Over Performance scott@slp53.sl.home (Scott Lurndal) - 2026-08-04 14:22 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-03 05:25 -0700
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-08-03 15:10 +0200
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-08-03 13:16 -0700
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-08-03 20:29 -0400
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-03 17:55 -0700
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-08-04 09:12 +0200
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-02 19:01 -0700
Re: Prioritize Performance over Correctness cross@spitfire.i.gajendra.net (Dan Cross) - 2026-08-03 19:59 +0000
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-30 03:50 -0700
Re: Prioritize Performance over Correctness "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-29 15:09 -0700
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-28 08:14 +0800
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 05:54 +0800
Re: Prioritize Performance over Correctness steveo@panix.com (Steven M. O'Neill) - 2026-07-31 20:34 +0000
Re: Prioritize Performance over Correctness James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-07-28 19:40 -0400
Re: Prioritize Performance over Correctness BGB <cr88192@gmail.com> - 2026-07-27 15:36 -0500
Re: Prioritize Performance over Correctness Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-29 04:56 +0800
Re: Prioritize Performance over Correctness Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-07-24 14:47 +0200
Re: Prioritize Performance over Correctness David Brown <david.brown@hesbynett.no> - 2026-07-24 16:27 +0200
Resources for Amateur Compiler Writers Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-25 00:52 +0800
Re: Resources for Amateur Compiler Writers bart <bc@freeuk.com> - 2026-07-24 23:08 +0100
Re: Resources for Amateur Compiler Writers BGB <cr88192@gmail.com> - 2026-07-24 18:50 -0500
Re: Resources for Amateur Compiler Writers Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-25 01:54 +0000
Re: Resources for Amateur Compiler Writers Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-25 15:20 +0800
Re: Resources for Amateur Compiler Writers Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-25 07:24 +0000
Re: Resources for Amateur Compiler Writers Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-25 15:30 +0800
Re: Resources for Amateur Compiler Writers David Brown <david.brown@hesbynett.no> - 2026-07-25 10:37 +0200
Re: Resources for Amateur Compiler Writers Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-27 00:35 +0800
Re: Resources for Amateur Compiler Writers BGB <cr88192@gmail.com> - 2026-07-26 12:39 -0500
Re: Resources for Amateur Compiler Writers bart <bc@freeuk.com> - 2026-07-26 22:27 +0100
Re: Resources for Amateur Compiler Writers BGB <cr88192@gmail.com> - 2026-07-26 18:02 -0500
Re: Resources for Amateur Compiler Writers Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-25 22:32 +0000
Re: Resources for Amateur Compiler Writers Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-25 15:58 -0700
Re: Resources for Amateur Compiler Writers David Brown <david.brown@hesbynett.no> - 2026-07-25 10:23 +0200
Re: Resources for Amateur Compiler Writers Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-24 16:29 -0700
Re: Resources for Amateur Compiler Writers Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-25 15:25 +0800
Re: Resources for Amateur Compiler Writers Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-25 15:33 -0700
Re: Resources for Amateur Compiler Writers Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-07-27 00:38 +0800
Re: Resources for Amateur Compiler Writers Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-26 17:06 -0700
Re: Resources for Amateur Compiler Writers Cóilín Nioclásín Glostéir <thanks-to@Taf.com> - 2026-07-26 17:03 +0000
Re: Prioritize Performance over Correctness BGB <cr88192@gmail.com> - 2026-07-24 16:50 -0500
Re: Prioritize Performance over Correctness Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-07-24 16:13 -0700
Re: Prioritize Performance over Correctness BGB <cr88192@gmail.com> - 2026-07-26 15:26 -0500
Re: Prioritize Performance over Correctness Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-07-23 11:18 +0200
Page 1 of 10 [1] 2 3 … 10 Next page →
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-07-22 01:38 +0200 |
| Subject | Prioritize Performance over Correctness |
| Message-ID | <113ovuj$23t9c$1@dont-email.me> |
There was some recent longish thread with discussions addressing Undefined Behavior. I just stumbled across a paper from Russ Cox on that topic with a provoking title.[*] I don't recall whether that had already been referenced anywhere in that thread; if not it might be of interest to some. A couple arguments and examples look familiar already, but I think it may be valuable anyway. Janis [*] https://research.swtch.com/ub
[toc] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-21 17:26 -0700 |
| Message-ID | <113p2o1$2es3m$1@kst.eternal-september.org> |
| In reply to | #400344 |
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
> There was some recent longish thread with discussions addressing
> Undefined Behavior. I just stumbled across a paper from Russ Cox
> on that topic with a provoking title.[*] I don't recall whether
> that had already been referenced anywhere in that thread; if not
> it might be of interest to some. A couple arguments and examples
> look familiar already, but I think it may be valuable anyway.
>
> Janis
>
> [*] https://research.swtch.com/ub
For those who don't follow the link, the full title of the paper is
"C and C++ Prioritize Performance over Correctness". (Your
paraphrase could be interpreted as advice, which I'm sure is not
how you intended it.)
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-07-22 01:50 +0000 |
| Message-ID | <113p7k8$27o$1@reader1.panix.com> |
| In reply to | #400345 |
In article <113p2o1$2es3m$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>> There was some recent longish thread with discussions addressing
>> Undefined Behavior. I just stumbled across a paper from Russ Cox
>> on that topic with a provoking title.[*] I don't recall whether
>> that had already been referenced anywhere in that thread; if not
>> it might be of interest to some. A couple arguments and examples
>> look familiar already, but I think it may be valuable anyway.
>>
>> Janis
>>
>> [*] https://research.swtch.com/ub
>
>For those who don't follow the link, the full title of the paper is
>"C and C++ Prioritize Performance over Correctness". (Your
>paraphrase could be interpreted as advice, which I'm sure is not
>how you intended it.)
From the post:
```
term% cat eraseall.c
#include <stdio.h>
#include <stdlib.h>
typedef void (*Function)(void);
static Function Do;
static void
baz(void)
{
printf("baz invoked.\n");
}
static void
bar(void)
{
baz();
}
void
foo(void)
{
Do = bar;
}
int
main(void)
{
Do();
return 0;
}
term% clang -O1 -Wall -Wextra -pedantic -std=c23 -o eraseall eraseall.c
term% ./eraseall
baz invoked.
term%
```
Something similar came up a month or so ago; recall my "what.c"
program:
```
term% cat what.c
#include <stdio.h>
int main(void) { for (unsigned int k = 0; k != 1; k += 2){} return 0; }
void hello(void) { printf("Hello, World!\n"); }
term% clang -O1 -Wall -Werror -pedantic -pedantic-errors -std=c23 -o what what.c
term% ./what
Hello, World!
term%
```
It's notable that the quoted text for the ANSI C standard also
says that an implementation is free to abort translation if it
encounters UB, which I recall was something that was a point of
concention in the earlier discussion. Kuyper posted a link to
a defect report that suggested that the compiler had to
translate the program if it could prove that (in that case,
manifest) UB was never triggered; however, that was from 1994,
and not normative anyhow. The committee has had ample time to
tune up the writing about this in the standard, and has chosen
not to: Cox's post is on-point; the current standard is deeply
flawed.
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-21 20:25 -0700 |
| Message-ID | <113pd7i$2hns9$1@kst.eternal-september.org> |
| In reply to | #400346 |
cross@spitfire.i.gajendra.net (Dan Cross) writes:
[...]
> ```
> term% cat eraseall.c
> #include <stdio.h>
> #include <stdlib.h>
>
> typedef void (*Function)(void);
>
> static Function Do;
>
> static void
> baz(void)
> {
> printf("baz invoked.\n");
> }
>
> static void
> bar(void)
> {
> baz();
> }
>
> void
> foo(void)
> {
> Do = bar;
> }
>
> int
> main(void)
> {
> Do();
> return 0;
> }
>
> term% clang -O1 -Wall -Wextra -pedantic -std=c23 -o eraseall eraseall.c
> term% ./eraseall
> baz invoked.
> term%
> ```
In that program, Do is a function pointer that's initialized to a null
pointer value (because it's static), so the call `Do()` has undefined
behavior.
> Something similar came up a month or so ago; recall my "what.c"
> program:
>
> ```
> term% cat what.c
> #include <stdio.h>
> int main(void) { for (unsigned int k = 0; k != 1; k += 2){} return 0; }
> void hello(void) { printf("Hello, World!\n"); }
> term% clang -O1 -Wall -Werror -pedantic -pedantic-errors -std=c23 -o what what.c
> term% ./what
> Hello, World!
> term%
> ```
That's an example of something more specific. N3220 6.8.6.1p4
gives explicit permission for an implementation to "assume" that
certain iteration statements will terminate. (I've said before
that I dislike this rule for several reasons.)
> It's notable that the quoted text for the ANSI C standard also
> says that an implementation is free to abort translation if it
> encounters UB, which I recall was something that was a point of
> concention in the earlier discussion. Kuyper posted a link to
> a defect report that suggested that the compiler had to
> translate the program if it could prove that (in that case,
> manifest) UB was never triggered; however, that was from 1994,
> and not normative anyhow.
C89 and all later editions of the C standard say (in a non-normative
note) that undefined behavior can include "terminating a
translation or execution (with the issuance of a diagnostic
message)". But almost all undefined behavior occurs at run time.
That could have been worded more clearly, but my interpretation
is that an implementation that detects that a source construct
has undefined behavior can terminate translation only if it can
prove that it's always executed. `if (0) 1/0;` does not permit
terminating translation.
> The committee has had ample time to
> tune up the writing about this in the standard, and has chosen
> not to: Cox's post is on-point; the current standard is deeply
> flawed.
How would you suggest fixing it?
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-07-22 17:37 +0000 |
| Message-ID | <113qv3t$ma0$1@reader1.panix.com> |
| In reply to | #400347 |
In article <113pd7i$2hns9$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>[...]
>> ```
>> term% cat eraseall.c
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> typedef void (*Function)(void);
>>
>> static Function Do;
>>
>> static void
>> baz(void)
>> {
>> printf("baz invoked.\n");
>> }
>>
>> static void
>> bar(void)
>> {
>> baz();
>> }
>>
>> void
>> foo(void)
>> {
>> Do = bar;
>> }
>>
>> int
>> main(void)
>> {
>> Do();
>> return 0;
>> }
>>
>> term% clang -O1 -Wall -Wextra -pedantic -std=c23 -o eraseall eraseall.c
>> term% ./eraseall
>> baz invoked.
>> term%
>> ```
>
>In that program, Do is a function pointer that's initialized to a null
>pointer value (because it's static), so the call `Do()` has undefined
>behavior.
Yup. UB gives the compiler permission to go wild.
>> Something similar came up a month or so ago; recall my "what.c"
>> program:
>>
>> ```
>> term% cat what.c
>> #include <stdio.h>
>> int main(void) { for (unsigned int k = 0; k != 1; k += 2){} return 0; }
>> void hello(void) { printf("Hello, World!\n"); }
>> term% clang -O1 -Wall -Werror -pedantic -pedantic-errors -std=c23 -o what what.c
>> term% ./what
>> Hello, World!
>> term%
>> ```
>
>That's an example of something more specific. N3220 6.8.6.1p4
>gives explicit permission for an implementation to "assume" that
>certain iteration statements will terminate. (I've said before
>that I dislike this rule for several reasons.)
Yup. This behavior indeed allowed by the standard, but that it
is allowed by the standard is, itself, an indictment of the
standard.
>> It's notable that the quoted text for the ANSI C standard also
>> says that an implementation is free to abort translation if it
>> encounters UB, which I recall was something that was a point of
>> concention in the earlier discussion. Kuyper posted a link to
>> a defect report that suggested that the compiler had to
>> translate the program if it could prove that (in that case,
>> manifest) UB was never triggered; however, that was from 1994,
>> and not normative anyhow.
>
>C89 and all later editions of the C standard say (in a non-normative
>note) that undefined behavior can include "terminating a
>translation or execution (with the issuance of a diagnostic
>message)". But almost all undefined behavior occurs at run time.
>That could have been worded more clearly, but my interpretation
>is that an implementation that detects that a source construct
>has undefined behavior can terminate translation only if it can
>prove that it's always executed. `if (0) 1/0;` does not permit
>terminating translation.
Unfortunately, the standard does not say that in normative text.
>> The committee has had ample time to
>> tune up the writing about this in the standard, and has chosen
>> not to: Cox's post is on-point; the current standard is deeply
>> flawed.
>
>How would you suggest fixing it?
Honestly? I don't think that it can be fixed. There are too
many competing interests, and C is the language that it is. I
do not think we're going to get away from that.
That said, a thing that they _could_ do is be more explicit
about when termination is allowed and so forth. The UB working
group is trying to reign in the undue dominance of UB, and I
give them credit for that; I don't know how far they will get,
though.
In the meanwhile, _most_ programmers should not be writing in C.
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2026-07-22 13:26 -0700 |
| Message-ID | <113r927$396f7$1@dont-email.me> |
| In reply to | #400346 |
On 7/21/2026 6:50 PM, Dan Cross wrote:
> #include <stdio.h>
> #include <stdlib.h>
>
> typedef void (*Function)(void);
>
> static Function Do;
>
> static void
> baz(void)
> {
> printf("baz invoked.\n");
> }
>
> static void
> bar(void)
> {
> baz();
> }
>
> void
> foo(void)
> {
> Do = bar;
> }
>
> int
> main(void)
> {
> Do();
> return 0;
> }
That should be a seg fault? Anyway:
_______________
#include <stdio.h>
#include <stdlib.h>
typedef void (*Function)(void);
static Function Do = NULL;
static void
baz(void)
{
printf("baz invoked.\n");
}
static void
bar(void)
{
baz();
}
void
foo(void)
{
Do = bar;
}
int
main(void)
{
foo(); // :^)
Do();
return 0;
}
_______________
Better? ;^)
[toc] | [prev] | [next] | [standalone]
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-07-22 07:33 +0200 |
| Message-ID | <113pkn9$23t9d$1@dont-email.me> |
| In reply to | #400345 |
On 2026-07-22 02:26, Keith Thompson wrote: > Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes: >> There was some recent longish thread with discussions addressing >> Undefined Behavior. I just stumbled across a paper from Russ Cox >> on that topic with a provoking title. [...] > > For those who don't follow the link, the full title of the paper is > "C and C++ Prioritize Performance over Correctness". (Your > paraphrase could be interpreted as advice, which I'm sure is not > how you intended it.) It was actually a (deliberate) "marketing trick" to provoke interest by reducing the title to an (IMO) yet more aggravating formulation. Yes, it was not my intention to suggest performance over correctness. (Would anyone?) Janis
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-07-22 10:41 +0200 |
| Message-ID | <113pvnb$2mr56$1@dont-email.me> |
| In reply to | #400348 |
On 22/07/2026 07:33, Janis Papanagnou wrote: > On 2026-07-22 02:26, Keith Thompson wrote: >> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes: >>> There was some recent longish thread with discussions addressing >>> Undefined Behavior. I just stumbled across a paper from Russ Cox >>> on that topic with a provoking title. [...] >> >> For those who don't follow the link, the full title of the paper is >> "C and C++ Prioritize Performance over Correctness". (Your >> paraphrase could be interpreted as advice, which I'm sure is not >> how you intended it.) > > It was actually a (deliberate) "marketing trick" to provoke interest > by reducing the title to an (IMO) yet more aggravating formulation. > > Yes, it was not my intention to suggest performance over correctness. > (Would anyone?) > Unfortunately, the answer to your final question is yes - and that is one of the reasons UB can be a problem. If by "correctness" you mean "code does what it should", people do sometimes release code that they know has bugs, but they know that fixing them would slow down the code - perhaps it is still good enough for their purposes at the time. More relevant to this discussion, if by "correct" code you mean code that has fully defined or appropriate implementation-defined behaviour (most code does not need to be fully portable) according to the C standards and/or platform or compiler extended semantics, then it is absolutely the case that programmers regularly prioritise performance over correctness by relying on UB. The result is code that works efficiently and as intended at the time, using tools tested by the developer. Then the UB bites the next person down the road that uses the same code in good faith, but with a different compiler or different options. If the reliance on the UB was unintentional, it's a bug - programmers are humans, they don't always know everything, and people make mistakes. But some programmers do so /knowing/ that the code is UB. Sometimes it is even stated in comments. The most common cases, IME, are reliance on two's complement wrapping, and messing with pointer casts to access data as different types, possibly with incorrect alignment. As for the linked paper, I am not particularly impressed by its arguments. I think it is fair enough to have different opinions about what should or should not be UB in language standards - and it is inarguably the case that some things that are UB could have defined behaviour at quite minor performance costs. (Note, however, that studies looking at the performance cost of disabling certain optimisations - such as "-fno-strict-aliasing" or "-fwrapv" - almost invariably use only x86 targets. x86 processors are designed to get the best from poorly optimised code, because that's what is often run on them, while most other processors except compilers to do more of the work. Compiler optimisations often have a much bigger impact on non-x86 targets and on processors with smaller relative memory latencies.) Fundamentally, the idea of "UB" is that it describes code that does not make sense, where there is no correct answer or meaningful specification of behaviour. What should it mean to dereference a pointer that does not point to a valid object of the type you are using? What should it mean to store a large result in a target type that is too small? Code that does this kind of thing is buggy - it cannot give correct answers. Nothing the compiler can do could make the code correct. The compiler's logic then goes like this: 1. UB is incorrect code. 2. C is a "trust the programmer" language. 3. The compiler assumes the programmer has written correct code. 4. Therefore, the programmer has not written code with UB. 5. Therefore, UB cannot happen. 6. Therefore the compiler can optimise on that assumption, such as by skipping some code generation. The only question is, is it a good idea for the compiler to be allowed to make the program "more wrong" ? I don't think it matters as much as people often think. It's easy to find or create examples where compiler optimisations on UB can amplify errors. Equally, however, you can find or create examples where assuming some kind of naïve "obvious" implementation of the UB code will also lead to bad results. Programs adding two positive integers are going to expect a positive result - a wrapped negative result is going to lead to tears. You need the same kind of care in development and testing no matter how the compiler treats its UB - and if you have done that job, these kinds of compiler optimisations do not significantly (IMHO) affect the risk of later problems. The killer point, however, is when you have received some code that you can justifiably assume is correct and well tested, but contains reliance on how certain types of UB happen to be implemented. It is not really any different than code that makes other undocumented assumptions, such as implementation-dependent details, reliance on certain files or OS features, timing requirements, etc. And compiling with "-fwrapv -fno-strict-aliasing" (if you are using a compiler that supports such features) will mitigate the most common cases of reliance on UB. As for the paper itself, I have a few points. It follows the time-worn path of complaining that "modern" compilers have distorted the "original" idea of UB and abuse it for optimisation in ways that are dangerous to the uninitiated. First, optimisation using UB is not new - I first used a compiler that assumed integer overflow does not wrap over thirty years ago. Second, compilers already default to "-O0" - if you know so little about your tools that you can't enable warnings, you won't have optimisation either. Third, improvements in compiler optimisation have gone hand-in-hand with improvements in compiler static error checking. Using "-Wall" along with optimisation will eliminate the solid majority of the risks and worries of the author. Fourth, the development of "sanitizers" not only allows far more UB to be found during testing, but it allows far more bugs to be found than would be possible if the mistakes were /not/ UB - "-fsanitize=signed-integer-overflow" catches overflow bugs precisely because it is UB in C, whereas if it were defines as wrapping then the mistake in the programmer's code would be correct as far as the language is concerned. Compilers are, of course, not perfect. But they are usually pretty good. Most of the paper could be scraped and replaced with the advice of always using "-Wall", possibly with "-Wextra" and/or fine-tuning of other warning flags, regardless of optimisation. And make use of sanitizers while testing. And always test with solid optimisations enabled (like "-O2"), though lower optimisations can be handy for fault-finding and debugging some aspects of code. It repeats the myths about signed integer overflow being UB because some computers have different representations of signed integers - C uses implementation-defined behaviour to handle implementation differences, and only resorts to UB when there is no sensible definition of "correct" behaviour, or where implementation-defined behaviour could have significant overhead costs. Both C++ (from C++20, IIRC) and C (from C23) allow only two's complement signed integer representations. Both committees made it clear that signed arithmetic overflow is still UB, because it does not lead to a sensible answer and allows optimisations and additional error checking. It is not hard to get wrapping behaviour if you want it (using conversions to and from unsigned types), and C23 introduced standardised checked arithmetic functions. As for infinite loops, loops with a constant controlling expression (like "for (;;)" ) are exempt from the "assumed to terminate" clause in C. I don't know if the example given was a bug in Clang or if it used C++ and C++ has different rules here. And in the next example, merging two loops into one, the merge won't introduce new bugs or race conditions - if another thread is using "count2", then there needs to be some kind of coordination (like atomics), and then the loops could not be merged anyway. I am not convinced that allowing the compiler to assume termination of certain types of loop is a particularly useful feature - it seems to me to be an added complication with very few potential benefits. But I can't see it being a problem for sensible working code either. Don't dereference null pointers. It's a bad idea. Read the specifications of the functions you want to use. std::sort requires a comparison function with a strict weak ordering - give it something else, and it's a user bug. Perhaps std::sort could have been specified in a nicer way, but that is hardly a compiler problem.
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-07-22 18:08 -0500 |
| Message-ID | <113rinb$3c4f8$2@dont-email.me> |
| In reply to | #400349 |
On 7/22/2026 3:41 AM, David Brown wrote:
> On 22/07/2026 07:33, Janis Papanagnou wrote:
>> On 2026-07-22 02:26, Keith Thompson wrote:
>>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>>>> There was some recent longish thread with discussions addressing
>>>> Undefined Behavior. I just stumbled across a paper from Russ Cox
>>>> on that topic with a provoking title. [...]
>>>
>>> For those who don't follow the link, the full title of the paper is
>>> "C and C++ Prioritize Performance over Correctness". (Your
>>> paraphrase could be interpreted as advice, which I'm sure is not
>>> how you intended it.)
>>
>> It was actually a (deliberate) "marketing trick" to provoke interest
>> by reducing the title to an (IMO) yet more aggravating formulation.
>>
>> Yes, it was not my intention to suggest performance over correctness.
>> (Would anyone?)
>>
>
> Unfortunately, the answer to your final question is yes - and that is
> one of the reasons UB can be a problem. If by "correctness" you mean
> "code does what it should", people do sometimes release code that they
> know has bugs, but they know that fixing them would slow down the code -
> perhaps it is still good enough for their purposes at the time.
>
Or, the cliche: "It's not a bug, it's a feature..."
> More relevant to this discussion, if by "correct" code you mean code
> that has fully defined or appropriate implementation-defined behaviour
> (most code does not need to be fully portable) according to the C
> standards and/or platform or compiler extended semantics, then it is
> absolutely the case that programmers regularly prioritise performance
> over correctness by relying on UB. The result is code that works
> efficiently and as intended at the time, using tools tested by the
> developer. Then the UB bites the next person down the road that uses
> the same code in good faith, but with a different compiler or different
> options.
>
Well, or for example, this pile of wonk:
#define gfxedit_getu16(ptr) (*(vol_u16p)(ptr))
#define gfxedit_getu32(ptr) (*(vol_u32p)(ptr))
#define gfxedit_getu64(ptr) (*(vol_u64p)(ptr))
#define gfxedit_setu16(ptr,val) (*(vol_u16p)(ptr)=(val))
#define gfxedit_setu32(ptr,val) (*(vol_u32p)(ptr)=(val))
#define gfxedit_setu64(ptr,val) (*(vol_u64p)(ptr)=(val))
Insert other versions for different platform constraints.
But, say:
u64 gfxedit_getu64(void *ptr)
{ u64 v; memcpy(&v, ptr, 8); return(v); }
Being also possible, but a significant performance penalty on some targets.
The situation is potentially much worse for big endian machines, but
these are rare at this point.
Say:
u16 gfxedit_getu16(void *ptr)
{ u16 v; v=((byte *)ptr)[0]|
(((u16)((byte *)ptr)[1]))<<8); return(v); }
u32 gfxedit_getu32(void *ptr)
{ u32 v; v=gfxedit_getu16(ptr)|
(((u32)gfxedit_getu16(((byte *)ptr)+2))<<16); return(v); }
u64 gfxedit_getu64(void *ptr)
{ u64 v; v=gfxedit_getu32(ptr)|
(((u64)gfxedit_getu32(((byte *)ptr)+4))<<32); return(v); }
Though, for BE machines, one wouldn't want to overuse these.
...
And, the function:
byte *gfxedit_memlzcpyf(byte *dst, byte *src, int len)
{
byte *cs, *ct, *cte;
u64 v0, v1;
int d;
int i;
d=dst-src;
if(d>len)
{
cs=src; ct=dst; cte=dst+len;
v0=gfxedit_getu64(cs); v1=gfxedit_getu64(cs+8);
gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v1);
cs+=16; ct+=16;
if(ct<cte)
{
v0=gfxedit_getu64(cs); v1=gfxedit_getu64(cs+8);
gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v1);
cs+=16; ct+=16;
if(ct<cte)
{
v0=gfxedit_getu64(cs); v1=gfxedit_getu64(cs+8);
gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v1);
cs+=16; ct+=16;
while(ct<cte)
{
v0=gfxedit_getu64(cs); v1=gfxedit_getu64(cs+8);
gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v1);
cs+=16; ct+=16;
}
}
}
return(cte);
}
if(d<=8)
{
if(d==1)
{
v0=*(byte *)src; v0|=(v0<<8); v0|=(v0<<16); v0|=(v0<<32);
ct=dst; cte=dst+len;
while(ct<cte)
{ gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v0); ct+=16; }
return(cte);
}
if(d==2)
{
v0=gfxedit_getu16(src); v0|=(v0<<16); v0|=(v0<<32);
ct=dst; cte=dst+len;
while(ct<cte)
{ gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v0); ct+=16; }
return(cte);
}
if(d==4)
{
v0=gfxedit_getu32(src); v0|=(v0<<32);
ct=dst; cte=dst+len;
while(ct<cte)
{ gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v0); ct+=16; }
return(cte);
}
if(d==8)
{
v0=gfxedit_getu64(src);
ct=dst; cte=dst+len;
while(ct<cte)
{ gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v0); ct+=16; }
return(cte);
}
if(d<0)
{
cs=src; ct=dst; cte=dst+len;
while(ct<cte)
{
v0=gfxedit_getu64(cs); v1=gfxedit_getu64(cs+8);
gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v1);
cs+=16; ct+=16;
}
return(cte);
}
if(d==3)
{
v0=gfxedit_getu32(src); v0=v0<<40; v0=(v0>>16)|(v0>>40);
ct=dst; cte=dst+len;
while(ct<cte)
{
gfxedit_setu64(ct+ 0, v0);
gfxedit_setu64(ct+ 6, v0);
gfxedit_setu64(ct+12, v0);
ct+=18;
}
return(cte);
}
if(d==5)
{
v0=gfxedit_getu64(src);
ct=dst; cte=dst+len;
while(ct<cte)
{ gfxedit_setu64(ct, v0); ct+=5; }
return(cte);
}
if(d==7)
{
v0=gfxedit_getu64(src);
ct=dst; cte=dst+len;
while(ct<cte)
{ gfxedit_setu64(ct, v0); ct+=7; }
return(cte);
}
cs=src; ct=dst; cte=dst+len;
while(ct<cte)
{ *ct++=*cs++; }
return(cte);
}
if(d>=16)
{
cs=src; ct=dst; cte=dst+len;
while(ct<cte)
{
v0=gfxedit_getu64(cs); v1=gfxedit_getu64(cs+8);
gfxedit_setu64(ct, v0); gfxedit_setu64(ct+8, v1);
cs+=16; ct+=16;
}
return(cte);
}
else
{
cs=src; ct=dst; cte=dst+len;
while(ct<cte)
{ v0=gfxedit_getu64(cs); gfxedit_setu64(ct, v0); cs+=8; ct+=8; }
return(cte);
}
}
Where one might ask, why not just:
byte *gfxedit_memlzcpyf(byte *dst, byte *src, int len)
{
int i, d;
d=dst-src;
if(d>len)
{ memcpy(dst, src, len); return(dst+len); }
if(d<0)
{ memmove(dst, src, len); return(dst+len); }
if(d==1)
{ memset(dst, *src, len); return(dst+len); }
for(i=0; i<len; i++)
dst[i]=src[i];
return(dst+len);
}
But, on the relevant implementation, trying to do the latter being
around an order of magnitude slower...
Note: Not on my target... Where I had added _memlzcpyf() as an extension
to the C library to avoid having to endlessly re-implement this stuff.
But, for other targets, it is still necessary.
Where, the 'f' variant is basically the variant that prioritizes speed
on the allowance that it may copy a little extra.
Well, except on SiFive chips where this in not the fastest option.
The fastest case for a SiFive style CPU being or similar, say:
byte *gfxedit_memlzcpyf(byte *dst, byte *src, int len)
{
byte *cs, *ct, *cte;
int i, d;
cs=src; ct=dst; cte=dst+len;
while(ct<cte)
{ *ct++=*cs++; }
return(cte);
}
But, for the original example, this works better on a CPU with higher
instruction latency, but the ability to use misaligned loads and stores
with zero added cost (whereas, the SiFive chips have lower
per-instruction latency but a very steep cost for misaligned memory
access; basically in the form of hidden trap-and-emulate).
Where, say, both CPU's can run RISc-V code, but have significant
differences in performance characteristics...
One might also want to use the latter naive byte copy for big endian
RISC machines (like on PowerPC or similar), ...
So, it can all turn into a big mess of cruft and ifdef's.
And, No:
You can't just use memmove() here...
In this case the typical repeating bytes on self-overlap behavior being
required for correct operation.
But, while small and elegant and portable, the above version would be
undesirable due to being around 10x slower.
One could try to detect alignment and then have separate aligned vs
unaligned loops, but in the use-case it gains very little and may end up
slower than always assuming misaligned (where it is a sort of chaos
where most of the copies are both misaligned and fairly short).
> If the reliance on the UB was unintentional, it's a bug - programmers
> are humans, they don't always know everything, and people make mistakes.
> But some programmers do so /knowing/ that the code is UB. Sometimes
> it is even stated in comments. The most common cases, IME, are reliance
> on two's complement wrapping, and messing with pointer casts to access
> data as different types, possibly with incorrect alignment.
>
>
> As for the linked paper, I am not particularly impressed by its arguments.
>
> I think it is fair enough to have different opinions about what should
> or should not be UB in language standards - and it is inarguably the
> case that some things that are UB could have defined behaviour at quite
> minor performance costs. (Note, however, that studies looking at the
> performance cost of disabling certain optimisations - such as "-fno-
> strict-aliasing" or "-fwrapv" - almost invariably use only x86 targets.
> x86 processors are designed to get the best from poorly optimised code,
> because that's what is often run on them, while most other processors
> except compilers to do more of the work. Compiler optimisations often
> have a much bigger impact on non-x86 targets and on processors with
> smaller relative memory latencies.)
>
The idea is that compilers should still try to produce efficient code
even with these semantic limitations.
> Fundamentally, the idea of "UB" is that it describes code that does not
> make sense, where there is no correct answer or meaningful specification
> of behaviour. What should it mean to dereference a pointer that does
> not point to a valid object of the type you are using? What should it
> mean to store a large result in a target type that is too small? Code
> that does this kind of thing is buggy - it cannot give correct answers.
> Nothing the compiler can do could make the code correct.
>
> The compiler's logic then goes like this:
>
> 1. UB is incorrect code.
> 2. C is a "trust the programmer" language.
> 3. The compiler assumes the programmer has written correct code.
> 4. Therefore, the programmer has not written code with UB.
> 5. Therefore, UB cannot happen.
> 6. Therefore the compiler can optimise on that assumption, such as by
> skipping some code generation.
>
> The only question is, is it a good idea for the compiler to be allowed
> to make the program "more wrong" ? I don't think it matters as much as
> people often think. It's easy to find or create examples where compiler
> optimisations on UB can amplify errors. Equally, however, you can find
> or create examples where assuming some kind of naïve "obvious"
> implementation of the UB code will also lead to bad results. Programs
> adding two positive integers are going to expect a positive result - a
> wrapped negative result is going to lead to tears. You need the same
> kind of care in development and testing no matter how the compiler
> treats its UB - and if you have done that job, these kinds of compiler
> optimisations do not significantly (IMHO) affect the risk of later
> problems.
>
> The killer point, however, is when you have received some code that you
> can justifiably assume is correct and well tested, but contains reliance
> on how certain types of UB happen to be implemented. It is not really
> any different than code that makes other undocumented assumptions, such
> as implementation-dependent details, reliance on certain files or OS
> features, timing requirements, etc. And compiling with "-fwrapv -fno-
> strict-aliasing" (if you are using a compiler that supports such
> features) will mitigate the most common cases of reliance on UB.
>
In some cases, it makes sense to assume that some things formally
considered UB would be better considered as Implementation Defined.
In practice, it likely wouldn't make that big of a difference; since
many cases the compiler still treats these cases is implementation
defined rather than true UB.
In this case, this leaves "true UB" as mostly cases where no sensible or
consistent behavior can be expected even within a given machine, say:
reliance on the values of uninitialized local variables;
going out of bounds on a conventional array (*1).
*1: I consider out-of-bounds within an array inside a struct to be a
partial exception, as one can reasonably assume that going OOB would
access other members within the same struct.
But, the relative ordering and layout of stack and global variables I
considered to be outside the scope of where valid assumptions can be
made in C.
However, such assumptions could be made for assembler...
Granted, in premise one could do, say:
extern u64 arr1[4];
extern u64 arr2[4];
__asm {
.section .data
.global arr1
.global arr2
arr1:
.quad 0
.quad 0
.quad 0
.quad 0
arr2:
.quad 0
.quad 0
.quad 0
.quad 0
};
And, arguably in this case one can argue that it may be valid to assume
that arr1 overflows into arr2.
But, then again, one also can't rely on the portability of __asm or
__asm__ blocks between targets. So, like with the structs, this would
exist more as a partial exception.
This example being partly N/A for GCC or similar, which uses a different
syntax for ASM blocks (well, and some compilers, like 64-bit MSVC,
having dropped support for inline ASM).
But, I had seen non-zero code which had relied on the assumption of
overflows carrying over consistently between global arrays.
In my compiler, such assumptions are not safe to be made, as the
compiler likes to shuffle the declarations around. Partly balancing
randomization and efficiency; as it can be more efficient to arrange
variables by usage frequency, and functions by a combination of
frequency and proximity. Say, ideally keeping commonly called functions
closer together, and if possible also clustering callers and callees
closer together. Even in the absence of profiler feedback, it tends to
make it such that the "cold path" is less likely to be part of the core
working set (and reducing the TLB miss frequency).
Did run into a little bit of a hassle recently that my compilers' output
tends to have a section alignment smaller than the page alignment, which
turned into a bit of pain trying to set up page access permissions for
the kernel binary (moving away from just setting the whole thing as RWX).
Ended up adding a few special case flags to the implementation of the
"mprotect" functionality:
INNER: Only applies to completely covered pages,
ignores partial pages.
Default: covers all pages in range.
ALLOW: Only allows new access, does not remove access.
DENY: Only removes access.
Default: New permissions fully replace old permissions.
These allowed dealing better with the partial page scenarios.
Can initially set the whole image READ|NOUSER;
Then use ALLOW to add WRITE/EXEC/USER to the relevant sections.
Maybe questionable, but there does exist a R|X|USER section.
Mostly has stuff for Syscalls and COM.
It is likely this part could be migrated into Userland.
Mostly it is a vestige of an earlier developmental stage.
>
> As for the paper itself, I have a few points.
>
> It follows the time-worn path of complaining that "modern" compilers
> have distorted the "original" idea of UB and abuse it for optimisation
> in ways that are dangerous to the uninitiated. First, optimisation
> using UB is not new - I first used a compiler that assumed integer
> overflow does not wrap over thirty years ago. Second, compilers already
> default to "-O0" - if you know so little about your tools that you can't
> enable warnings, you won't have optimisation either. Third,
> improvements in compiler optimisation have gone hand-in-hand with
> improvements in compiler static error checking. Using "-Wall" along
> with optimisation will eliminate the solid majority of the risks and
> worries of the author. Fourth, the development of "sanitizers" not only
> allows far more UB to be found during testing, but it allows far more
> bugs to be found than would be possible if the mistakes were /not/ UB -
> "-fsanitize=signed-integer-overflow" catches overflow bugs precisely
> because it is UB in C, whereas if it were defines as wrapping then the
> mistake in the programmer's code would be correct as far as the language
> is concerned.
>
For keeping old code working, it makes sense to assume wrapping.
But, maybe it could make sense to have a semantic distinction for cases
where wrapping is assumed vs where it is likely unintentional.
My proposal, if any, would be, say:
If "signed" is used explicitly, it means wrap-on-overflow is expected.
So, say:
int i;
signed int v;
If 'i' overflows, one can question whether or not it was intended; but
if 'v' overflows, assume it is intentional (as with 'unsigned').
This being in part because an explicit "signed" keyword is uncommon to
be used with normal counting/index type variables.
> Compilers are, of course, not perfect. But they are usually pretty
> good. Most of the paper could be scraped and replaced with the advice
> of always using "-Wall", possibly with "-Wextra" and/or fine-tuning of
> other warning flags, regardless of optimisation. And make use of
> sanitizers while testing. And always test with solid optimisations
> enabled (like "-O2"), though lower optimisations can be handy for fault-
> finding and debugging some aspects of code.
>
> It repeats the myths about signed integer overflow being UB because some
> computers have different representations of signed integers - C uses
> implementation-defined behaviour to handle implementation differences,
> and only resorts to UB when there is no sensible definition of "correct"
> behaviour, or where implementation-defined behaviour could have
> significant overhead costs.
>
> Both C++ (from C++20, IIRC) and C (from C23) allow only two's complement
> signed integer representations. Both committees made it clear that
> signed arithmetic overflow is still UB, because it does not lead to a
> sensible answer and allows optimisations and additional error checking.
> It is not hard to get wrapping behaviour if you want it (using
> conversions to and from unsigned types), and C23 introduced standardised
> checked arithmetic functions.
>
>
> As for infinite loops, loops with a constant controlling expression
> (like "for (;;)" ) are exempt from the "assumed to terminate" clause in
> C. I don't know if the example given was a bug in Clang or if it used
> C++ and C++ has different rules here.
>
> And in the next example, merging two loops into one, the merge won't
> introduce new bugs or race conditions - if another thread is using
> "count2", then there needs to be some kind of coordination (like
> atomics), and then the loops could not be merged anyway. I am not
> convinced that allowing the compiler to assume termination of certain
> types of loop is a particularly useful feature - it seems to me to be an
> added complication with very few potential benefits. But I can't see it
> being a problem for sensible working code either.
>
> Don't dereference null pointers. It's a bad idea.
>
Dereferencing NULL is one of those cases where the most sensible option
is to treat it as a fault...
Most sensible option is to assume that trying to dereference NULL is
unintentional (given the main purpose of NULL being as a "this object
doesn't exist" pointer).
But:
Assuming it doesn't happen and then removing the offending code path
entirely is also bad IMO. However, turning the code-path into a break
instruction or similar (following any other externally visible side
effects) would still likely be acceptable IMO (or, at least, less bad in
this case than just continuing down the other path as if nothing had
ever happened).
> Read the specifications of the functions you want to use. std::sort
> requires a comparison function with a strict weak ordering - give it
> something else, and it's a user bug. Perhaps std::sort could have been
> specified in a nicer way, but that is hardly a compiler problem.
>
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-07-23 10:31 +0200 |
| Message-ID | <113sjg8$3k0q6$1@dont-email.me> |
| In reply to | #400358 |
On 23/07/2026 01:08, BGB wrote:
> On 7/22/2026 3:41 AM, David Brown wrote:
>> On 22/07/2026 07:33, Janis Papanagnou wrote:
>>> On 2026-07-22 02:26, Keith Thompson wrote:
>>>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>>>>> There was some recent longish thread with discussions addressing
>>>>> Undefined Behavior. I just stumbled across a paper from Russ Cox
>>>>> on that topic with a provoking title. [...]
>>>>
>>>> For those who don't follow the link, the full title of the paper is
>>>> "C and C++ Prioritize Performance over Correctness". (Your
>>>> paraphrase could be interpreted as advice, which I'm sure is not
>>>> how you intended it.)
>>>
>>> It was actually a (deliberate) "marketing trick" to provoke interest
>>> by reducing the title to an (IMO) yet more aggravating formulation.
>>>
>>> Yes, it was not my intention to suggest performance over correctness.
>>> (Would anyone?)
>>>
>>
>> Unfortunately, the answer to your final question is yes - and that is
>> one of the reasons UB can be a problem. If by "correctness" you mean
>> "code does what it should", people do sometimes release code that they
>> know has bugs, but they know that fixing them would slow down the code
>> - perhaps it is still good enough for their purposes at the time.
>>
>
> Or, the cliche: "It's not a bug, it's a feature..."
>
Possibly.
But it is always important to remember that different types of software
require different levels of quality control - it can be acceptable to
have known bugs ("undocumented features" or "undocumented limitations")
in some software. If video games were coded with the same level of care
used for jet engine controllers, they would never make it to market.
>
>> More relevant to this discussion, if by "correct" code you mean code
>> that has fully defined or appropriate implementation-defined behaviour
>> (most code does not need to be fully portable) according to the C
>> standards and/or platform or compiler extended semantics, then it is
>> absolutely the case that programmers regularly prioritise performance
>> over correctness by relying on UB. The result is code that works
>> efficiently and as intended at the time, using tools tested by the
>> developer. Then the UB bites the next person down the road that uses
>> the same code in good faith, but with a different compiler or
>> different options.
>>
>
>
> Well, or for example, this pile of wonk:
>
> #define gfxedit_getu16(ptr) (*(vol_u16p)(ptr))
> #define gfxedit_getu32(ptr) (*(vol_u32p)(ptr))
> #define gfxedit_getu64(ptr) (*(vol_u64p)(ptr))
> #define gfxedit_setu16(ptr,val) (*(vol_u16p)(ptr)=(val))
> #define gfxedit_setu32(ptr,val) (*(vol_u32p)(ptr)=(val))
> #define gfxedit_setu64(ptr,val) (*(vol_u64p)(ptr)=(val))
>
> Insert other versions for different platform constraints.
While details of volatile accesses are implementation-dependent, they
can be a successful way of accessing the underlying memory for data.
It's easy to get things wrong, however, if you are not consistent about
it. And too much use can lead to inefficiencies as well.
>
> But, say:
> u64 gfxedit_getu64(void *ptr)
> { u64 v; memcpy(&v, ptr, 8); return(v); }
> Being also possible, but a significant performance penalty on some targets.
>
That's the challenge. memcpy() is often a good, safe and correct way to
access data as though it were a different type, but not all compilers
optimise it well in such cases. Making code that is correct on a range
of implementations, and also efficient on a range of implementations, is
the hard part. So sometimes people end up with code that is efficienct
on the implementations they use, works on those, but is reliant on UB
and fails on other implementations.
> The situation is potentially much worse for big endian machines, but
> these are rare at this point.
>
> Say:
> u16 gfxedit_getu16(void *ptr)
> { u16 v; v=((byte *)ptr)[0]|
> (((u16)((byte *)ptr)[1]))<<8); return(v); }
> u32 gfxedit_getu32(void *ptr)
> { u32 v; v=gfxedit_getu16(ptr)|
> (((u32)gfxedit_getu16(((byte *)ptr)+2))<<16); return(v); }
> u64 gfxedit_getu64(void *ptr)
> { u64 v; v=gfxedit_getu32(ptr)|
> (((u64)gfxedit_getu32(((byte *)ptr)+4))<<32); return(v); }
>
> Though, for BE machines, one wouldn't want to overuse these.
>
On good modern compilers, that sort of thing is usually fine, and you
would expect it to reduce to a single "load 64-bit with endian swap"
instruction or minimal similar sequence.
As I see it, the main problem of UB and compilers is /not/ as commonly
believed, overly-enthusiastic compilers that optimise on assumptions
about UB. The problem is poorer or older compilers that don't optimise
the correct code well, forcing people who need efficient results to
spend a lot of effort finding alternative solutions that might be
reliant on UB. It also doesn't help that some developers don't enable
optimisation or otherwise fail to use their tools well.
<snip code>
>
> But, on the relevant implementation, trying to do the latter being
> around an order of magnitude slower...
It sounds like it might make more sense to write improved memcpy, memove
and memset implementations for the implementation in question!
>
> So, it can all turn into a big mess of cruft and ifdef's.
>
Maximum efficiency is /always/ going to be implementation and target
dependent. It is fine, for low-level functions where the speed matters,
to have a variety of implementations tuned to different targets, with
fall-back to something that is correct portable code. The use of
#ifdef's (or separate files) means you can also happily use
compiler-specific extensions, pragmas, attributes, builtins, etc., or
even inline assembly.
>> The killer point, however, is when you have received some code that
>> you can justifiably assume is correct and well tested, but contains
>> reliance on how certain types of UB happen to be implemented. It is
>> not really any different than code that makes other undocumented
>> assumptions, such as implementation-dependent details, reliance on
>> certain files or OS features, timing requirements, etc. And compiling
>> with "-fwrapv -fno- strict-aliasing" (if you are using a compiler that
>> supports such features) will mitigate the most common cases of
>> reliance on UB.
>>
>
> In some cases, it makes sense to assume that some things formally
> considered UB would be better considered as Implementation Defined.
No, never. You might want that to be the case (and I am sure we all
have our personal favourite UB's from the C standards that we would
rather have as IB, or unspecified, or the up-coming "erroneous
behaviour" - though we would not agree entirely on which UB's). But you
can't just say "I think left-shift of negative numbers should be IB" and
assume it to be the case!
>
> In practice, it likely wouldn't make that big of a difference; since
> many cases the compiler still treats these cases is implementation
> defined rather than true UB.
>
Particular implementations can, of course, document the way a particular
type of UB is implemented - then when you are using that compiler, you
can rely on that behaviour.
Relying on undocumented treatment of UB is where you get in trouble.
The code might work as you want with this version of the compiler, and
fail with the next version.
>
> But, I had seen non-zero code which had relied on the assumption of
> overflows carrying over consistently between global arrays.
>
Relying on the details of how generated assembly is organised is a
high-risk game. I have had occasions when I needed to do so, but it's
tightly tied to exact tool versions and flags, and needs checking for
every run of the build.
>
>>
>> As for the paper itself, I have a few points.
>>
>> It follows the time-worn path of complaining that "modern" compilers
>> have distorted the "original" idea of UB and abuse it for optimisation
>> in ways that are dangerous to the uninitiated. First, optimisation
>> using UB is not new - I first used a compiler that assumed integer
>> overflow does not wrap over thirty years ago. Second, compilers
>> already default to "-O0" - if you know so little about your tools that
>> you can't enable warnings, you won't have optimisation either. Third,
>> improvements in compiler optimisation have gone hand-in-hand with
>> improvements in compiler static error checking. Using "-Wall" along
>> with optimisation will eliminate the solid majority of the risks and
>> worries of the author. Fourth, the development of "sanitizers" not
>> only allows far more UB to be found during testing, but it allows far
>> more bugs to be found than would be possible if the mistakes were /
>> not/ UB - "-fsanitize=signed-integer-overflow" catches overflow bugs
>> precisely because it is UB in C, whereas if it were defines as
>> wrapping then the mistake in the programmer's code would be correct as
>> far as the language is concerned.
>>
>
> For keeping old code working, it makes sense to assume wrapping.
To be clear - you mean that if you don't know the old code, it makes
sense to assume the code might rely on wrapping behaviour, and use
appropriate compiler flags (or add appropriate pragmas) ?
>
> But, maybe it could make sense to have a semantic distinction for cases
> where wrapping is assumed vs where it is likely unintentional.
>
> My proposal, if any, would be, say:
> If "signed" is used explicitly, it means wrap-on-overflow is expected.
That makes no sense at all.
>
> So, say:
> int i;
> signed int v;
> If 'i' overflows, one can question whether or not it was intended; but
> if 'v' overflows, assume it is intentional (as with 'unsigned').
You can't just invent a personal convention like that - at least, not if
you ever use other people's code or compilers written by someone else.
You can't change the meaning of existing code.
If C were ever to have support for something akin to that, I would
expect to see new names involved. It would be "_Wrapping int v;", or
types "int_wrapping32_t" in <stdint.h>.
More likely, functions like "wrapping_add" could be added to <stdckdint.h>.
>
> This being in part because an explicit "signed" keyword is uncommon to
> be used with normal counting/index type variables.
>
Some people use it - and they do not do so with the expectation of
different semantics than when it is omitted. Some people write "signed"
rather than "int" for declarations.
>>
>> Don't dereference null pointers. It's a bad idea.
>>
>
> Dereferencing NULL is one of those cases where the most sensible option
> is to treat it as a fault...
It's a bug.
>
> Most sensible option is to assume that trying to dereference NULL is
> unintentional (given the main purpose of NULL being as a "this object
> doesn't exist" pointer).
>
Yes.
There is the exception that on some hardware, 0 is a valid memory
address and you might want to access it. On microcontrollers, it is not
uncommon for code flash to start there, so something like an integrity
check of the program would have to read that address. Then you are
dereferencing a pointer that happens to have value 0, rather than a null
pointer.
> But:
> Assuming it doesn't happen and then removing the offending code path
> entirely is also bad IMO. However, turning the code-path into a break
> instruction or similar (following any other externally visible side
> effects) would still likely be acceptable IMO (or, at least, less bad in
> this case than just continuing down the other path as if nothing had
> ever happened).
>
You are thinking of code like :
int x = *p;
if (!p) return someone_made_a_mistake;
...
Some compilers will skip the check here, because they assume the
hardware / OS will have caught the attempt to access address 0. That is
fair enough - /if/ the target is guaranteed to have such a hardware
catch. If it is not guaranteed, then the check can't be skipped. Even
better, of course, would be a compiler warning that the programmer is
doing something silly - whether or not the check is skipped.
I agree that sometimes a "break" (or "trap", or similar) instruction can
be a good thing for compilers to generate when they are clearly
executing undefined behaviour. But I am not convinced it is always a
good idea (I would not want it for this case), and it would be hard to
specify and guarantee the circumstances without it ruining the
possibility of optimisation from assuming code has defined behaviour.
Compilers with sanitizers do support such traps - gcc with the options
"-fsanitize-trap=all -fsanitize=null" will trap if the pointer "p" is
null in this code.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-23 14:31 -0700 |
| Message-ID | <113u16u$6bo3$1@kst.eternal-september.org> |
| In reply to | #400364 |
David Brown <david.brown@hesbynett.no> writes:
[...]
> You are thinking of code like :
>
> int x = *p;
> if (!p) return someone_made_a_mistake;
> ...
>
> Some compilers will skip the check here, because they assume the
> hardware / OS will have caught the attempt to access address 0. That
> is fair enough - /if/ the target is guaranteed to have such a hardware
> catch. If it is not guaranteed, then the check can't be skipped.
Yes, it can. A conforming compiler can omit the (!p) test because the
behavior is undefined, not (necessarily) because of the behavior of the
target system.
> Even better, of course, would be a compiler warning that the
> programmer is doing something silly - whether or not the check is
> skipped.
Certainly a warning would be nice. The problem is that unexpected
optimizations in the presence of undefined behavior don't always occur
because the compiler *knows* that the behavior is undefined.
[...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-23 14:48 -0700 |
| Message-ID | <113u27c$6bo3$2@kst.eternal-september.org> |
| In reply to | #400371 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> You are thinking of code like :
>>
>> int x = *p;
>> if (!p) return someone_made_a_mistake;
>> ...
>>
>> Some compilers will skip the check here, because they assume the
>> hardware / OS will have caught the attempt to access address 0. That
>> is fair enough - /if/ the target is guaranteed to have such a hardware
>> catch. If it is not guaranteed, then the check can't be skipped.
>
> Yes, it can. A conforming compiler can omit the (!p) test because the
> behavior is undefined, not (necessarily) because of the behavior of the
> target system.
Sorry, I was imprecise.
If p is a null pointer, the behavior is undefined. If p is a
valid non-null pointer, the behavior is well defined, and the
`return someone_made_a_mistake;` statement will be executed. Since
returning `someone_made_a_mistake` is a valid example of undefined
behavior, a compiler can simplify the code to an unconditional
`return someone_made_a_mistake;`.
It can't just omit checks because the behavior *might* be undefined.
>> Even better, of course, would be a compiler warning that the
>> programmer is doing something silly - whether or not the check is
>> skipped.
>
> Certainly a warning would be nice. The problem is that unexpected
> optimizations in the presence of undefined behavior don't always occur
> because the compiler *knows* that the behavior is undefined.
>
> [...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-23 15:11 -0700 |
| Message-ID | <113u3j5$7cq1$1@kst.eternal-september.org> |
| In reply to | #400372 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> David Brown <david.brown@hesbynett.no> writes:
>> [...]
>>> You are thinking of code like :
>>>
>>> int x = *p;
>>> if (!p) return someone_made_a_mistake;
>>> ...
>>>
>>> Some compilers will skip the check here, because they assume the
>>> hardware / OS will have caught the attempt to access address 0. That
>>> is fair enough - /if/ the target is guaranteed to have such a hardware
>>> catch. If it is not guaranteed, then the check can't be skipped.
>>
>> Yes, it can. A conforming compiler can omit the (!p) test because the
>> behavior is undefined, not (necessarily) because of the behavior of the
>> target system.
>
> Sorry, I was imprecise.
Sorry, I was also *wrong*.
> If p is a null pointer, the behavior is undefined. If p is a
> valid non-null pointer, the behavior is well defined, and the
> `return someone_made_a_mistake;` statement will be executed. Since
> returning `someone_made_a_mistake` is a valid example of undefined
> behavior, a compiler can simplify the code to an unconditional
> `return someone_made_a_mistake;`.
Correction: if p is a valid non-null pointer, the behavior is well
defined, and the `return someone_made_a_mistake;` statement will *NOT*
be executed. A conforming compiler can emit code that does nothing.
For that matter, the behavior is undefined if p is an invalid non-null
pointer, so that dereferencing it has UB.
> It can't just omit checks because the behavior *might* be undefined.
>
>>> Even better, of course, would be a compiler warning that the
>>> programmer is doing something silly - whether or not the check is
>>> skipped.
>>
>> Certainly a warning would be nice. The problem is that unexpected
>> optimizations in the presence of undefined behavior don't always occur
>> because the compiler *knows* that the behavior is undefined.
>>
>> [...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-07-24 09:23 +0200 |
| Message-ID | <113v3u3$gi3r$1@dont-email.me> |
| In reply to | #400373 |
On 24/07/2026 00:11, Keith Thompson wrote: > Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: >> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: >>> David Brown <david.brown@hesbynett.no> writes: >>> [...] >>>> You are thinking of code like : >>>> >>>> int x = *p; >>>> if (!p) return someone_made_a_mistake; >>>> ... >>>> >>>> Some compilers will skip the check here, because they assume the >>>> hardware / OS will have caught the attempt to access address 0. That >>>> is fair enough - /if/ the target is guaranteed to have such a hardware >>>> catch. If it is not guaranteed, then the check can't be skipped. >>> >>> Yes, it can. A conforming compiler can omit the (!p) test because the >>> behavior is undefined, not (necessarily) because of the behavior of the >>> target system. See below for more discussion. In the case of gcc's "-fdelete-null-pointer-checks" flag, the compiler documentation says that look-after-you-leap null pointer checks can be eliminated because the compiler assumes that any dereferencing of address zero results in a trap. The big fuss when this flag was introduced (and enabled by default) in gcc was because the Linux kernel contained such mistakes in the code, and by default address 0 was accessible without causing a trap. >> >> Sorry, I was imprecise. > > Sorry, I was also *wrong*. > >> If p is a null pointer, the behavior is undefined. If p is a >> valid non-null pointer, the behavior is well defined, and the >> `return someone_made_a_mistake;` statement will be executed. Since >> returning `someone_made_a_mistake` is a valid example of undefined >> behavior, a compiler can simplify the code to an unconditional >> `return someone_made_a_mistake;`. > > Correction: if p is a valid non-null pointer, the behavior is well > defined, and the `return someone_made_a_mistake;` statement will *NOT* > be executed. A conforming compiler can emit code that does nothing. > (Caveat - what I am about to write is the best of my understanding, but it might not be correct. If I am wrong, I am happy to be corrected!) The trouble with your argument here is that a pointer with value 0 is not necessarily a null pointer (and I'm assuming an implementation where null pointers have a value 0, not anything weirder than that). Null pointers are generated from null pointer constants - 0, (void*) 0, and nullptr. If you have a pointer that happens to contain the value 0 but it did not come from a null pointer constant, it is not a null pointer and dereferencing it is not inherently UB. (Of course it is still UB if it does not point to a valid object of appropriate type.) The evaluation of "!p" is based on a comparison of "p" to the value 0 - it will be true if p contains the value 0. (This point is perhaps the weak link in my reasoning - maybe "!p" is only true if "p" is actually a null pointer. However, I am confident that all real implementations, where null pointers are value 0, act by comparison of the value.) As far as I can see, therefore, "p" can be a valid pointer to an object of appropriate type, not be a null pointer, and still have value 0 and have "!p" evaluate to 1. > For that matter, the behavior is undefined if p is an invalid non-null > pointer, so that dereferencing it has UB. > Agreed. Of course, a compiler can only optimise away UB code if it knows it is UB - the compiler usually cannot know that a general pointer is invalid. >> It can't just omit checks because the behavior *might* be undefined. >> >>>> Even better, of course, would be a compiler warning that the >>>> programmer is doing something silly - whether or not the check is >>>> skipped. >>> >>> Certainly a warning would be nice. The problem is that unexpected >>> optimizations in the presence of undefined behavior don't always occur >>> because the compiler *knows* that the behavior is undefined. >>> Yes, indeed. And compilers are built up with lots of passes and do not hold all information throughout the chain (otherwise they would be a lot bigger, a lot slower, and use a lot more memory). Often by the time code is eliminated or re-arranged in later passes, the original reason is lost. Older versions of gcc had a warning you could enable to tell you when code was eliminated - the warning was removed because it was too noisy in the face of more advanced optimisations (like code folding, constant propagation, and function cloning), and there was no practical reliable way to give just the helpful cases. We can always wish for better warnings, and keep asking for them from our compiler vendors, but the compiler writers are unfortunately limited by practical realities.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-24 03:14 -0700 |
| Message-ID | <113vdth$johs$1@kst.eternal-september.org> |
| In reply to | #400382 |
David Brown <david.brown@hesbynett.no> writes:
> On 24/07/2026 00:11, Keith Thompson wrote:
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>>> David Brown <david.brown@hesbynett.no> writes:
>>>> [...]
>>>>> You are thinking of code like :
>>>>>
>>>>> int x = *p;
>>>>> if (!p) return someone_made_a_mistake;
>>>>> ...
>>>>>
>>>>> Some compilers will skip the check here, because they assume the
>>>>> hardware / OS will have caught the attempt to access address 0. That
>>>>> is fair enough - /if/ the target is guaranteed to have such a hardware
>>>>> catch. If it is not guaranteed, then the check can't be skipped.
>>>>
>>>> Yes, it can. A conforming compiler can omit the (!p) test because the
>>>> behavior is undefined, not (necessarily) because of the behavior of the
>>>> target system.
>
> See below for more discussion.
>
> In the case of gcc's "-fdelete-null-pointer-checks" flag, the compiler
> documentation says that look-after-you-leap null pointer checks can be
> eliminated because the compiler assumes that any dereferencing of
> address zero results in a trap. The big fuss when this flag was
> introduced (and enabled by default) in gcc was because the Linux
> kernel contained such mistakes in the code, and by default address 0
> was accessible without causing a trap.
That's the gcc documentation's rationale for its behavior --
and that's perfectly valid. My point is that evaluating *p
if p is a null pointer has undefined behavior in the language
(in the abstract machine), and therefore the condition !p
can be true when it's evaluated only if the previous line has
already had undefined behavior. A conforming C compiler could
implement the optimization (of not generating code for `return
someone_made_a_mistake;) regardless of the target system's actual
behavior on defererencing a null pointer -- even if, for example,
evaluating `*p` on a null pointer always yielded a consistent value
(say, 0 of p is of type int*).
If a null pointer is represented as all-bits-zero and dereferencing
an all-bits-zero pointer is likely to be a sensible thing to do,
then a *useful* compiler is likely -- but a *standard-conforming*
compiler isn't required to do so.
>>> Sorry, I was imprecise.
>> Sorry, I was also *wrong*.
>>
>>> If p is a null pointer, the behavior is undefined. If p is a
>>> valid non-null pointer, the behavior is well defined, and the
>>> `return someone_made_a_mistake;` statement will be executed. Since
>>> returning `someone_made_a_mistake` is a valid example of undefined
>>> behavior, a compiler can simplify the code to an unconditional
>>> `return someone_made_a_mistake;`.
>> Correction: if p is a valid non-null pointer, the behavior is well
>> defined, and the `return someone_made_a_mistake;` statement will *NOT*
>> be executed. A conforming compiler can emit code that does nothing.
>
> (Caveat - what I am about to write is the best of my understanding,
> but it might not be correct. If I am wrong, I am happy to be
> corrected!)
>
> The trouble with your argument here is that a pointer with value 0 is
> not necessarily a null pointer (and I'm assuming an implementation
> where null pointers have a value 0, not anything weirder than that).
>
> Null pointers are generated from null pointer constants - 0, (void*)
> 0, and nullptr. If you have a pointer that happens to contain the
> value 0 but it did not come from a null pointer constant, it is not a
> null pointer and dereferencing it is not inherently UB. (Of course it
> is still UB if it does not point to a valid object of appropriate
> type.)
So you're restricting the discussion to systems where a null pointer is
represented as all-bits-zero. I don't think that makes any difference
to the abstract semantics, but I'll accept it.
A null pointer constant, when converted to a pointer type, yields
a null pointer value, so that's *one* way to obtain a null pointer
value -- but it's not the only one. malloc(SIZE_MAX) or
fopen("", "") will almost certainly return a null pointer value
as well, and that's just as null as one obtained by evaluating
`nullptr` or `(void*)0`. In particular, `malloc(SIZE_MAX) == nullptr`
will very probably evaluate to 1.
On the other hand, there are issues of "provenance", such that a pointer
value obtained by `memset(ptr_obj, 0, sizeof ptr_obj)` has the same
representation as a null pointer but might not qualify as one in certain
circumstances. But I don't understand that issue well enough to discuss
it.
> The evaluation of "!p" is based on a comparison of "p" to the value 0
> - it will be true if p contains the value 0. (This point is perhaps
> the weak link in my reasoning - maybe "!p" is only true if "p" is
> actually a null pointer. However, I am confident that all real
> implementations, where null pointers are value 0, act by comparison of
> the value.)
The evaluation of `!p` yields 0 if p compares unequal to 0, 1 if
it compares equal to 0. It's equivalent to `p == 0`. In that
comparison, the right operand is implicitly converted to a null
pointer of the type of p. In other words, `!p` means precisely
"the value of p is a null pointer value", or "p is a null pointer".
> As far as I can see, therefore, "p" can be a valid pointer to an
> object of appropriate type, not be a null pointer, and still have
> value 0 and have "!p" evaluate to 1.
Only in the presence of undefined behavior, in which case the value
of "p" can be a lovely shade of blue.
>> For that matter, the behavior is undefined if p is an invalid non-null
>> pointer, so that dereferencing it has UB.
>>
>
> Agreed.
>
> Of course, a compiler can only optimise away UB code if it knows it is
> UB - the compiler usually cannot know that a general pointer is
> invalid.
>
>>> It can't just omit checks because the behavior *might* be undefined.
>>>
>>>>> Even better, of course, would be a compiler warning that the
>>>>> programmer is doing something silly - whether or not the check is
>>>>> skipped.
>>>>
>>>> Certainly a warning would be nice. The problem is that unexpected
>>>> optimizations in the presence of undefined behavior don't always occur
>>>> because the compiler *knows* that the behavior is undefined.
>>>>
>
> Yes, indeed. And compilers are built up with lots of passes and do
> not hold all information throughout the chain (otherwise they would be
> a lot bigger, a lot slower, and use a lot more memory). Often by the
> time code is eliminated or re-arranged in later passes, the original
> reason is lost. Older versions of gcc had a warning you could enable
> to tell you when code was eliminated - the warning was removed because
> it was too noisy in the face of more advanced optimisations (like code
> folding, constant propagation, and function cloning), and there was no
> practical reliable way to give just the helpful cases. We can always
> wish for better warnings, and keep asking for them from our compiler
> vendors, but the compiler writers are unfortunately limited by
> practical realities.
Often the optimizations and other transformations are performed on
intermediate forms that can't easily be described in terms of the
source code.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2026-07-24 14:56 +0000 |
| Message-ID | <t2L8S.522644$lkZe.245771@fx14.iad> |
| In reply to | #400382 |
David Brown <david.brown@hesbynett.no> writes: >On 24/07/2026 00:11, Keith Thompson wrote: >> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: >>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: >>>> David Brown <david.brown@hesbynett.no> writes: >>>> [...] >>>>> You are thinking of code like : >>>>> >>>>> int x = *p; >>>>> if (!p) return someone_made_a_mistake; >>>>> ... >>>>> >>>>> Some compilers will skip the check here, because they assume the >>>>> hardware / OS will have caught the attempt to access address 0. That >>>>> is fair enough - /if/ the target is guaranteed to have such a hardware >>>>> catch. If it is not guaranteed, then the check can't be skipped. >>>> >>>> Yes, it can. A conforming compiler can omit the (!p) test because the >>>> behavior is undefined, not (necessarily) because of the behavior of the >>>> target system. > >See below for more discussion. > >In the case of gcc's "-fdelete-null-pointer-checks" flag, the compiler >documentation says that look-after-you-leap null pointer checks can be >eliminated because the compiler assumes that any dereferencing of >address zero results in a trap. The big fuss when this flag was >introduced (and enabled by default) in gcc was because the Linux kernel >contained such mistakes in the code, and by default address 0 was >accessible without causing a trap. It's worth pointing out one of the big differences between System V and BSD unix operating systems - where the latter would map a read-only page of zeros at address zero on the VAX - in which case loads via a NULL pointer would return zeros, and stores would fault. System V would fault on such reads. This bit more than a few programmers at the time.
[toc] | [prev] | [next] | [standalone]
| From | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-07-25 16:30 +0000 |
| Message-ID | <1142oc0$14b1e$1@paganini.bofh.team> |
| In reply to | #400382 |
David Brown <david.brown@hesbynett.no> wrote:
> On 24/07/2026 00:11, Keith Thompson wrote:
>
> The trouble with your argument here is that a pointer with value 0 is
> not necessarily a null pointer (and I'm assuming an implementation where
> null pointers have a value 0, not anything weirder than that).
>
> Null pointers are generated from null pointer constants - 0, (void*) 0,
> and nullptr. If you have a pointer that happens to contain the value 0
> but it did not come from a null pointer constant, it is not a null
> pointer and dereferencing it is not inherently UB. (Of course it is
> still UB if it does not point to a valid object of appropriate type.)
>
> The evaluation of "!p" is based on a comparison of "p" to the value 0 -
> it will be true if p contains the value 0. (This point is perhaps the
> weak link in my reasoning - maybe "!p" is only true if "p" is actually a
> null pointer. However, I am confident that all real implementations,
> where null pointers are value 0, act by comparison of the value.)
>
> As far as I can see, therefore, "p" can be a valid pointer to an object
> of appropriate type, not be a null pointer, and still have value 0 and
> have "!p" evaluate to 1.
I did not check the standard, but if the standard allows this, then
this is clearly a bug in the standard. To say it differently,
any C compiler when '!p' can evaluate to 1 for pointer p to a valid
object is broken. Implementing '!p' via machine level comparison
to 0 works only when null pointer is represented by 0, otherwise
compiler must to whatever is necessary to get right result of the
comparison.
--
Waldek Hebisch
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2026-07-27 09:33 -0400 |
| Message-ID | <1147mnu$37r54$1@dont-email.me> |
| In reply to | #400405 |
On 2026-07-25 12:30, Waldek Hebisch wrote: > David Brown <david.brown@hesbynett.no> wrote: ...>> The evaluation of "!p" is based on a comparison of "p" to the value 0 - >> it will be true if p contains the value 0. ... False. >> ... (This point is perhaps the >> weak link in my reasoning - maybe "!p" is only true if "p" is actually a >> null pointer. ... Correct. >> ... However, I am confident that all real implementations, >> where null pointers are value 0, ... I doubt that - if it were true, there would be pressure on the committee to mandate such a representation. >> ... act by comparison of the value.) >> As far as I can see, therefore, "p" can be a valid pointer to an object >> of appropriate type, not be a null pointer, and still have value 0 and >> have "!p" evaluate to 1. > > I did not check the standard, but if the standard allows this, then > this is clearly a bug in the standard. The standard is quite clear. !p returns 0 if p compares equal to 0, and 1 otherwise. When a pointer is compared with 0, the 0 gets implicitly converted to a null pointer of the same type. All null pointers compare equal. Therefore !p tests whether 0 is a null pointer, not whether it has a representation with all bits cleared.
[toc] | [prev] | [next] | [standalone]
| From | Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> |
|---|---|
| Date | 2026-07-28 00:22 +0800 |
| Message-ID | <ABL9S.9473$1xtd.2670@fx01.ams4> |
| In reply to | #400444 |
On 27/07/2026 9:33 PM, James Kuyper wrote: > On 2026-07-25 12:30, Waldek Hebisch wrote: >> David Brown <david.brown@hesbynett.no> wrote: > ...>> The evaluation of "!p" is based on a comparison of "p" to the > value 0 - >>> it will be true if p contains the value 0. ... > > False. > >>> ... (This point is perhaps the >>> weak link in my reasoning - maybe "!p" is only true if "p" is actually a >>> null pointer. ... > > Correct. > >>> ... However, I am confident that all real implementations, >>> where null pointers are value 0, ... > > I doubt that - if it were true, there would be pressure on the committee > to mandate such a representation. > >>> ... act by comparison of the value.) >>> As far as I can see, therefore, "p" can be a valid pointer to an object >>> of appropriate type, not be a null pointer, and still have value 0 and >>> have "!p" evaluate to 1. >> >> I did not check the standard, but if the standard allows this, then >> this is clearly a bug in the standard. > > The standard is quite clear. !p returns 0 if p compares equal to 0, and > 1 otherwise. When a pointer is compared with 0, the 0 gets implicitly > converted to a null pointer of the same type. All null pointers compare > equal. Therefore !p tests whether 0 is a null pointer, not whether it > has a representation with all bits cleared. > I'm not in a position to do so yet, but you can trivially test this by implementing "the null pointer" to be internally represented by 0xff..ff where the .. represents your bitwith; 16bit, 32bit, 64bit, 128bit. Then one of the first thing you notice, is that the integer zero needs to convert to the 0xff..ff bit pattern when cast to a pointer. After that, implementing !p is trivial, for some value of trivial. Happy compiler building! -- Johann | email: invalid -> com | http://www.myrkraverk.com/blog/ I'm not from the Internet, I just work there. | via Easynews.com
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-07-27 12:58 -0700 |
| Message-ID | <1148d9b$3fv8p$1@kst.eternal-september.org> |
| In reply to | #400445 |
Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> writes:
> On 27/07/2026 9:33 PM, James Kuyper wrote:
[...]
>> The standard is quite clear. !p returns 0 if p compares equal to 0,
>> and
>> 1 otherwise. When a pointer is compared with 0, the 0 gets implicitly
>> converted to a null pointer of the same type. All null pointers compare
>> equal. Therefore !p tests whether 0 is a null pointer, not whether it
>> has a representation with all bits cleared.
>
> I'm not in a position to do so yet, but you can trivially test this by
> implementing "the null pointer" to be internally represented by 0xff..ff
> where the .. represents your bitwith; 16bit, 32bit, 64bit, 128bit.
>
> Then one of the first thing you notice, is that the integer zero needs
> to convert to the 0xff..ff bit pattern when cast to a pointer. After
> that, implementing !p is trivial, for some value of trivial.
You'd have to create a compiler, or modify an existing one, to use a
non-zero representation for null pointers. That's hardly "trivial".
(For example, default initialization for static objects could no
longer just zero the target object.)
I don't think there are any modern C compilers that don't use
all-bits-zero for null pointers. Other representations are of
course valid, but tend not to be worth the trouble.
I wouldn't be terribly surprised if a future standard mandated
all-bits-zero for null pointers -- or if it didn't.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
Page 1 of 10 [1] 2 3 … 10 Next page →
Back to top | Article view | comp.lang.c
csiph-web