Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #399456 > unrolled thread
| Started by | fir <profesor.fir@gmail.com> |
|---|---|
| First post | 2026-05-27 19:53 +0200 |
| Last post | 2026-05-30 11:18 +0200 |
| Articles | 20 on this page of 459 — 24 participants |
Back to article view | Back to comp.lang.c
this girl calls c ugly fir <profesor.fir@gmail.com> - 2026-05-27 19:53 +0200
Re: this girl calls c ugly fir <profesor.fir@gmail.com> - 2026-05-27 20:15 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-27 18:49 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 04:53 +0000
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 02:35 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 23:32 +0000
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 20:07 -0500
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-28 11:48 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-28 09:18 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 04:57 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 23:35 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 09:52 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-29 05:20 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-29 13:22 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-29 15:16 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-30 13:52 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-30 14:40 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-30 16:36 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-30 15:48 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 11:14 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-31 13:25 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 22:14 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 15:22 +0200
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-30 03:49 +0000
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-05-28 12:47 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 09:56 +0200
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-05-29 11:00 -0700
Re: this girl calls c ugly fir <profesor.fir@gmail.com> - 2026-05-28 17:12 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 14:07 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 23:54 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 10:02 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 12:19 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 14:46 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 14:22 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 17:15 +0200
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-05-29 15:59 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 17:12 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 18:48 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 19:09 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:00 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 22:14 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 12:09 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 17:05 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 18:34 +0200
Re: this girl calls c ugly tTh <tth@none.invalid> - 2026-05-29 19:29 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 18:53 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 12:28 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 20:49 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:03 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 13:56 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 22:54 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 15:52 -0700
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-29 20:31 -0400
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 02:03 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 19:02 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 12:12 +0100
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-05-30 12:29 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 13:56 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-30 16:43 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-31 03:37 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-30 19:53 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 12:16 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 11:47 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 12:55 +0200
Re: this girl calls c ugly Richard Harnden <richard.nospam@gmail.invalid> - 2026-05-31 09:12 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 11:49 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-31 11:10 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 13:18 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 10:24 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 17:35 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 12:46 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 22:24 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 18:26 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 08:28 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 15:54 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 08:39 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 02:33 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 11:48 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-02 06:37 -0400
Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-02 05:06 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 16:28 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 03:37 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 16:31 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 13:36 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 23:49 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 18:04 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:10 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 23:50 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-08 02:20 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-08 12:39 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-08 23:15 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-08 18:51 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-09 09:46 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-09 15:07 -0700
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-09 01:25 +0000
Re: Constants and undefined behavior James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-09 18:29 -0400
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-09 16:01 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-10 12:36 +0000
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 16:49 +0200
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-11 15:20 +0000
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 18:08 +0200
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-11 16:30 +0000
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 20:52 +0200
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-12 02:20 +0000
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-13 14:57 +0200
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-21 15:26 -0700
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-22 03:40 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 07:50 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-21 14:26 -0700
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-22 03:56 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-29 06:27 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 15:47 -0700
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-06 16:36 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 16:43 -0700
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-06 17:41 -0700
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-05 10:41 +0200
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 10:49 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 16:15 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 18:06 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-07 22:34 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-08 23:05 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-09 10:19 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-09 15:12 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-10 14:37 +0000
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-10 18:30 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-10 14:55 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-10 23:32 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-10 14:47 -0700
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-11 08:56 +0200
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-11 11:38 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-11 14:05 +0200
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-11 15:38 -0700
Re: Constants and undefined behavior scott@slp53.sl.home (Scott Lurndal) - 2026-06-11 23:07 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-11 17:43 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-12 02:02 +0000
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 17:34 +0200
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-12 10:58 +0200
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-12 12:27 -0700
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-13 12:36 +0200
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-13 12:03 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-14 12:35 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-13 12:02 +0000
Re: Constants and undefined behavior ram@zedat.fu-berlin.de (Stefan Ram) - 2026-06-13 12:13 +0000
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-13 12:44 +0000
Re: Constants and undefined behavior ram@zedat.fu-berlin.de (Stefan Ram) - 2026-06-14 17:22 +0000
Re: Constants and undefined behavior scott@slp53.sl.home (Scott Lurndal) - 2026-06-14 21:24 +0000
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-15 17:52 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-13 18:32 +0200
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-14 14:33 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-14 22:02 +0200
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-14 15:55 -0700
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-15 10:09 +0200
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-15 10:43 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-15 16:01 +0200
Re: Constants and undefined behavior antispam@fricas.org (Waldek Hebisch) - 2026-06-15 17:57 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-16 10:10 +0200
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-24 17:45 +0200
Re: Constants and undefined behavior "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-24 12:27 -0700
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-24 16:58 +0200
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-15 19:26 +0000
Re: Constants and undefined behavior James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-15 21:59 -0400
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-16 04:59 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-29 05:41 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-29 15:23 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 07:36 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-08-18 20:27 +0000
Re: Constants and undefined behavior Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-20 04:12 +0800
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-11 13:29 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-12 02:08 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-12 11:02 +0200
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 17:45 +0200
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-10 15:11 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-10 22:44 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-10 16:19 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-11 11:50 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-11 16:28 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-11 23:46 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-11 18:29 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-12 01:54 +0000
Re: Constants and undefined behavior David Brown <david.brown@hesbynett.no> - 2026-06-12 11:37 +0200
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 07:58 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-08-18 20:28 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 05:35 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-02 06:29 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 16:10 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 15:29 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 06:41 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 11:24 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-08 08:35 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-08 17:33 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-09 00:54 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-09 10:08 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-08 13:40 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 09:37 -0700
Meaning of "expression" Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-08 14:05 -0700
Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-09 15:17 +0200
Re: Expression statements (was Re: Meaning of "expression") Bart <bc@freeuk.com> - 2026-06-09 14:53 +0100
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-09 16:30 +0200
Re: Expression statements (was Re: Meaning of "expression") David Brown <david.brown@hesbynett.no> - 2026-06-09 17:13 +0200
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-09 15:34 -0700
Re: Expression statements (was Re: Meaning of "expression") David Brown <david.brown@hesbynett.no> - 2026-06-10 09:04 +0200
Re: Expression statements (was Re: Meaning of "expression") Bart <bc@freeuk.com> - 2026-06-10 11:10 +0100
Re: Expression statements (was Re: Meaning of "expression") David Brown <david.brown@hesbynett.no> - 2026-06-10 13:29 +0200
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-10 03:17 -0700
Re: Expression statements (was Re: Meaning of "expression") David Brown <david.brown@hesbynett.no> - 2026-06-10 13:43 +0200
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-10 14:08 -0700
Re: Expression statements (was Re: Meaning of "expression") David Brown <david.brown@hesbynett.no> - 2026-06-11 09:10 +0200
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 20:29 +0200
Re: Expression statements (was Re: Meaning of "expression") David Brown <david.brown@hesbynett.no> - 2026-06-12 12:55 +0200
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-13 15:01 +0200
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-11 20:12 +0200
Re: Expression statements (was Re: Meaning of "expression") James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-11 15:13 -0400
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-12 00:37 +0200
Re: Expression statements (was Re: Meaning of "expression") scott@slp53.sl.home (Scott Lurndal) - 2026-06-11 23:05 +0000
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-12 01:18 +0200
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-11 17:41 -0700
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-28 02:49 +0200
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-27 21:00 -0700
Re: Expression statements (was Re: Meaning of "expression") Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-28 09:52 -0700
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-28 18:28 -0700
Re: Expression statements (was Re: Meaning of "expression") Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-14 13:40 -0700
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-14 14:13 -0700
Re: Expression statements (was Re: Meaning of "expression") Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-19 08:32 -0700
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-19 15:09 -0700
Re: Expression statements (was Re: Meaning of "expression") James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-11 20:41 -0400
Re: Expression statements (was Re: Meaning of "expression") Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-28 03:16 +0200
Re: Expression statements (was Re: Meaning of "expression") tTh <tth@none.invalid> - 2026-06-09 19:27 +0200
Re: Expression statements (was Re: Meaning of "expression") Bart <bc@freeuk.com> - 2026-06-09 19:19 +0100
Re: Expression statements (was Re: Meaning of "expression") Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-09 15:22 -0700
Re: Meaning of "expression" Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 00:42 -0700
The meaning of 42 ; (was: Re: Meaning of "expression") Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-15 19:42 +0800
Re: Meaning of "expression" Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-15 05:36 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:22 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 23:56 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-07 13:37 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-07 15:09 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-08 02:33 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 09:37 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-15 17:29 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-08-18 20:30 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-08 00:16 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-08 12:41 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-08 17:37 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-09 16:05 +0200
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-02 13:59 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 13:05 +0000
Parentheses (was: this girl calls c ugly) Bart <bc@freeuk.com> - 2026-06-02 14:38 +0100
Re: Parentheses (was: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 15:19 +0000
Re: Parentheses antispam@fricas.org (Waldek Hebisch) - 2026-06-03 22:30 +0000
Re: Parentheses Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-03 16:24 -0700
Re: Parentheses antispam@fricas.org (Waldek Hebisch) - 2026-06-04 02:03 +0000
Re: Parentheses Bart <bc@freeuk.com> - 2026-06-04 01:12 +0100
Re: Parentheses antispam@fricas.org (Waldek Hebisch) - 2026-06-04 01:58 +0000
Re: Parentheses Bart <bc@freeuk.com> - 2026-06-04 11:37 +0100
Re: Parentheses cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 10:51 +0000
Re: Parentheses Bart <bc@freeuk.com> - 2026-06-04 12:47 +0100
Re: Parentheses Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 14:57 +0200
Re: Parentheses cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 14:31 +0000
[OT] Fancy graphics (was Re: this girl calls c ugly) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 15:54 +0200
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Bart <bc@freeuk.com> - 2026-06-02 15:19 +0100
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 15:19 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 17:39 +0200
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 16:36 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) scott@slp53.sl.home (Scott Lurndal) - 2026-06-02 21:33 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-02 14:43 -0700
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) ram@zedat.fu-berlin.de (Stefan Ram) - 2026-06-02 17:08 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 19:19 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-04 00:11 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 15:39 -0700
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-03 13:14 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-02 15:10 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 15:31 +0000
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 10:15 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 16:29 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 03:45 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 04:02 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 09:04 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-31 18:11 +0100
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-05-31 19:34 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 19:10 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 11:12 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 12:36 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 14:26 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 02:34 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 12:40 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 14:35 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 14:18 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 15:47 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 15:57 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 16:27 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 16:46 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 20:15 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 20:54 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 20:29 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 14:06 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 22:47 +0100
Famous (hopefully last) words [on this topic] Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-05 00:27 +0200
Re: Famous (hopefully last) words [on this topic] Bad Post <invalid@invalid.invalid> - 2026-06-05 01:20 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 16:09 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 00:44 +0100
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-04 17:26 -0700
Re: this girl calls c ugly antispam@fricas.org (Waldek Hebisch) - 2026-06-05 12:58 +0000
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-05 14:27 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 02:47 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 00:53 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 11:04 +0100
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 05:34 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:45 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:44 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-06 07:39 +0200
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-04 15:25 -0700
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-12 08:31 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-05 09:29 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 12:39 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-05 15:42 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 16:50 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 11:09 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 20:29 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 16:18 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 17:23 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 16:47 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 19:57 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 20:34 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 22:28 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 21:58 +0000
Re: this girl calls c ugly Richard Harnden <richard.nospam@gmail.invalid> - 2026-06-04 23:25 +0100
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 02:49 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 19:47 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 21:04 +0200
Re: this girl calls c ugly Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2026-06-04 19:13 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-05 10:34 +0200
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-07-12 08:32 +0000
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-07-12 11:05 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 12:11 -0700
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-04 16:33 -0400
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 14:16 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 00:02 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 18:36 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 02:54 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 05:49 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 11:01 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 11:53 -0700
Re: this girl calls c ugly Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2026-06-04 18:45 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 20:19 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 20:31 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 20:41 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 20:49 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 00:03 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-05 00:18 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 03:02 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-05 14:04 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:49 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-06 15:13 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-06 17:53 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 11:59 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 15:21 +0200
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 06:38 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 09:52 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 02:42 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 12:50 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 11:47 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 12:55 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 14:39 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 15:11 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 08:41 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 02:07 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 11:38 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 05:01 -0700
It is not futile to change the subject line (Was: this girl calls c ugly) gazelle@shell.xmission.com (Kenny McCormack) - 2026-06-02 12:39 +0000
Re: It is not futile to change the subject line (Was: this girl calls c ugly) gazelle@shell.xmission.com (Kenny McCormack) - 2026-06-02 12:42 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 11:46 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-02 11:09 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 05:25 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-02 14:20 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 15:12 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-02 04:16 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-01 15:23 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 16:06 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 23:24 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 11:35 +0200
Operator precedence in other (non-C, but "C-like") languages (Was: something about a girl) gazelle@shell.xmission.com (Kenny McCormack) - 2026-06-02 12:36 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-01 11:04 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 14:04 +0200
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-01 18:48 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 21:04 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 09:17 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 09:09 +0200
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 12:07 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 14:37 +0200
Microcontroller software stacks (was Re: this girl calls c ugly) scott@slp53.sl.home (Scott Lurndal) - 2026-06-02 15:06 +0000
Re: Microcontroller software stacks (was Re: this girl calls c ugly) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-21 14:13 -0700
Re: Microcontroller software stacks (was Re: this girl calls c ugly) David Brown <david.brown@hesbynett.no> - 2026-06-22 08:58 +0200
Re: Microcontroller software stacks (was Re: this girl calls c ugly) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-22 03:35 -0700
Re: Microcontroller software stacks (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-22 10:50 +0000
Re: Microcontroller software stacks (was Re: this girl calls c ugly) David Brown <david.brown@hesbynett.no> - 2026-06-22 12:59 +0200
Storage needed when there are bit-field members Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-28 09:42 -0700
Re: Storage needed when there are bit-field members Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-28 18:06 -0700
Re: Storage needed when there are bit-field members Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-28 20:20 -0700
Re: Storage needed when there are bit-field members Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-14 14:56 -0700
Re: Storage needed when there are bit-field members scott@slp53.sl.home (Scott Lurndal) - 2026-08-14 22:30 +0000
Re: Storage needed when there are bit-field members Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 16:10 -0700
Re: Storage needed when there are bit-field members scott@slp53.sl.home (Scott Lurndal) - 2026-08-16 15:20 +0000
Re: Storage needed when there are bit-field members antispam@fricas.org (Waldek Hebisch) - 2026-08-19 19:34 +0000
Re: Storage needed when there are bit-field members Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-19 15:26 -0700
Re: Storage needed when there are bit-field members David Brown <david.brown@hesbynett.no> - 2026-08-20 11:00 +0200
Re: Storage needed when there are bit-field members Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-20 03:30 -0700
Re: Storage needed when there are bit-field members David Brown <david.brown@hesbynett.no> - 2026-08-20 13:58 +0200
Re: Storage needed when there are bit-field members scott@slp53.sl.home (Scott Lurndal) - 2026-08-20 14:50 +0000
Re: Storage needed when there are bit-field members Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-14 14:19 -0700
Re: Microcontroller software stacks (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-22 10:45 +0000
Re: Microcontroller software stacks (was Re: this girl calls c ugly) scott@slp53.sl.home (Scott Lurndal) - 2026-06-22 15:23 +0000
Re: Microcontroller software stacks (was Re: this girl calls c ugly) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-14 13:23 -0700
Re: Microcontroller software stacks (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-08-18 20:32 +0000
Re: Microcontroller software stacks (was Re: this girl calls c ugly) scott@slp53.sl.home (Scott Lurndal) - 2026-06-22 15:04 +0000
Re: Microcontroller software stacks (was Re: this girl calls c ugly) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-22 13:02 -0700
Re: Microcontroller software stacks Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-14 12:51 -0700
Re: Microcontroller software stacks Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-15 05:02 +0800
Re: Microcontroller software stacks bart <bc@freeuk.com> - 2026-08-15 01:18 +0100
Re: Microcontroller software stacks Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-16 13:52 +0800
Re: Microcontroller software stacks Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-14 14:06 -0700
Re: Microcontroller software stacks scott@slp53.sl.home (Scott Lurndal) - 2026-08-14 21:42 +0000
Re: Microcontroller software stacks Michael S <already5chosen@yahoo.com> - 2026-08-15 22:13 +0300
Re: Microcontroller software stacks scott@slp53.sl.home (Scott Lurndal) - 2026-08-15 19:39 +0000
Re: Microcontroller software stacks Michael S <already5chosen@yahoo.com> - 2026-08-15 23:22 +0300
Re: Microcontroller software stacks scott@slp53.sl.home (Scott Lurndal) - 2026-08-16 14:38 +0000
Re: Microcontroller software stacks Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-08-16 16:11 -0700
Re: Microcontroller software stacks Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 16:16 -0700
Re: Microcontroller software stacks cross@spitfire.i.gajendra.net (Dan Cross) - 2026-08-18 20:34 +0000
Re: Microcontroller software stacks antispam@fricas.org (Waldek Hebisch) - 2026-08-19 19:57 +0000
Re: Microcontroller software stacks Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-08-15 17:31 -0700
Re: Microcontroller software stacks (was Re: this girl calls c ugly) Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-08-20 04:51 +0800
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 03:58 -0700
Re: this girl calls c ugly dave_thompson_2@comcast.net - 2026-06-06 19:02 -0400
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-05-31 19:11 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 16:08 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 16:32 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 17:12 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-30 14:07 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 18:10 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 19:18 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:17 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 21:47 +0100
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-29 15:57 -0400
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:34 +0200
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-29 23:18 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 01:26 +0100
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-30 04:25 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 12:01 +0100
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-31 00:29 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-31 10:59 +0100
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-01 00:33 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 02:26 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 13:24 +0200
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-29 08:09 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-29 04:15 -0500
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-29 14:58 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-30 01:04 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-29 23:20 +0000
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-30 11:18 +0200
Page 8 of 23 — ← Prev page 1 … 6 7 [8] 9 10 … 23 Next page →
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2026-08-14 12:35 -0700 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <86ecg07aw2.fsf@linuxsc.com> |
| In reply to | #400004 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: > David Brown <david.brown@hesbynett.no> writes: [...] >> I think the semantics of this "loops can be assumed to terminate" >> are clearly defined in the standard. [...] > > I disagree that the semantics are clearly defined. N3220 6.8.6.1p4 > is specified in terms of what an implementation may "assume", not in > terms of the semantics of the program. It isn't obvious that the semantics of "may be assumed to terminate" is even well defined by the text of the C standard; it certainly is not clearly defined. > One can conclude that this > means that the program has undefined behavior if the assumption is > violated, but that's not directly stated. I don't know how many C > programmers know the standard well enough to reach that conclusion. > I'm not even 100% sure it's accurate. > > The permission was added in C11 with little fanfare. It's not > mentioned in the list of major changes in the C11 Foreword. > The cases where it applies may be rarer than I had assumed, but > it at least has the potential to break existing code that was well > defined in C99. > > The rationale is to provide more opportunities for optimization, > but it's not at all clear (at least to me) that it's particularly > successful. If cases where it can cause problems are rare, then > presumably cases where it's actually useful are rare. (That may > be an oversimplification.) If someone is counting votes my vote is to remove this rule from the C standard. If there were a compiler option to act as though this rule were not in force I would always use that option. It's worse than useless.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-13 12:02 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110jgsg$4ll$1@reader1.panix.com> |
| In reply to | #399960 |
In article <110ghmv$21vi3$1@dont-email.me>, David Brown <david.brown@hesbynett.no> wrote: >[snip] >As for my '"modern compilers are evil" crowd' comment, there are people >(not anyone involved in this discussion) who really do fall into that >camp. I've seen people who are experienced and respected developers >make all sorts of accusations to compiler developers, claiming they are >only interested in high scores on synthetic benchmarks and directly >insulting their motivations and integrity, blaming them for "breaking" >their code that relied on the effects of some kinds of UB. It is always >frustrating when you have code that works fine with one compiler >version, but using another compiler results in failure due to UB in your >code - especially if writing correct code gives inefficient results with >the first compiler. And it's fine to say you'd be happier if a >particular thing that is UB in C were not UB - but it is unreasonable to >blame compiler developers for implementing the language as it is defined. Eh...I think those people have a point. Note, I don't think that "modern compilers are evil" (I mean, wow, that's a strong word) and I certainly do not think it is appropriate to malign the people who write them personally over what one does with code. But I _do_ think it is fair to say that UB is very easy to fall into in C, that programs that have worked correctly (insofar as their intended behavior as written) for years can suddenly fail because latent UB is treated differently in a point revision of a compiler, and that that (as you point out) can be incredibly frustrating for the authors. Regehr called out a dichotomy with UB: programmers using a language hate it; compiler writers love it. Here's my own vignette: I was chatting with a friend who works on LLVM and clang some time ago. I said, "I don't want UB" and he replied, "no, you really do." I asked him what he meant and he responded that I wanted a compiler that is capable of optimizing my program; "sure, but I still don't want UB." We went on for a bit, and it became clear that he saw UB as _the_ vehicle for unlocking optimization. I realized that we were not speaking the same language _at all_. He and I both wanted a language where we could write programs that yield efficient object code. He saw UB as essential for that; but what I want is a language with well-defined semantics that can be aggressively optimized. That, I think, is the tension: there was a fundamental breakdown in communication between the users of the language, and those defining and implementing it. My subjective sense is that in the past few years things are getting somewhat better, but it is hard to evolve something as critical and widely used as C. >I am not in any way saying that critics of aspects of C (the language, >the standards, or compiler implementations) should be dismissed or >despised - merely that the example of loop elimination leading to UB and >unexpected results is regularly used as "evidence" by those that hold >extreme positions about C, despite it being very unrealistic for the >issue to cause problems in real coding practice. The kernel I am working on has about 5 million lines of code. That code has been evolving for 40 years; some of it predates the ISO standards and even the ANSI standard. It has been updated for newer compilers, sure, but in some places the treatment is surface-level: using ISO-style function prototypes and definition syntax, for example. But deep problems remain in parts, and contraints on engineering resources couple with economic and business pressures so that it's not going to get cleaned up any time soon. I'm sure there is UB in it; in fact, I know there is. But them's the breaks; and yet, customers are using it in production. Because of this, upgrading toolchains is laborious and complex, and takes a lot of time, and new compilers are (rightly) viewed with suspicion. That is not a great situation, but I don't think anyone is angry at the compiler people over it. And just as it's not acceptable to blame compiler writers for implementating the language as it is defined, it's not really acceptable to blame programmers either; some of the people who put the UB there are (literally) dead, and there's just not enough time in the day to go clean it all up. I wish there was more compassion for that. As said earlier, C is what it is. I suspect that it will continue to make incremental improvements, but we're basically stuck with what we have. - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | ram@zedat.fu-berlin.de (Stefan Ram) |
|---|---|
| Date | 2026-06-13 12:13 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <video-20260613131240@ram.dialup.fu-berlin.de> |
| In reply to | #400024 |
cross@spitfire.i.gajendra.net (Dan Cross) wrote or quoted: >Here's my own vignette: I was chatting with a friend who works >on LLVM and clang some time ago. I said, "I don't want UB" and >he replied, "no, you really do." I asked him what he meant and Might like to have a look at the video "Garbage In, Garbage Out, Arguing about Undefined Behavior with Nasal Demons" (2016) by Chandler Carruth. IIRC it essential takes the point of your friend, but maybe adds some explanations. At 15' in, it discusses the suggestion to "define all the behavior". It's for C++, but I think some of it might apply to C as well. At 24' come some examples.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-13 12:44 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110jjbd$7p7$1@reader1.panix.com> |
| In reply to | #400026 |
In article <video-20260613131240@ram.dialup.fu-berlin.de>, Stefan Ram <ram@zedat.fu-berlin.de> wrote: >cross@spitfire.i.gajendra.net (Dan Cross) wrote or quoted: >>Here's my own vignette: I was chatting with a friend who works >>on LLVM and clang some time ago. I said, "I don't want UB" and >>he replied, "no, you really do." I asked him what he meant and > > Might like to have a look at the video > >"Garbage In, Garbage Out, Arguing about Undefined Behavior >with Nasal Demons" (2016) by Chandler Carruth. > > IIRC it essential takes the point of your friend, but maybe adds > some explanations. At 15' in, it discusses the suggestion to > "define all the behavior". It's for C++, but I think some of it > might apply to C as well. At 24' come some examples. I'm not a huge fan of Carruth. - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | ram@zedat.fu-berlin.de (Stefan Ram) |
|---|---|
| Date | 2026-06-14 17:22 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <UB-20260614180434@ram.dialup.fu-berlin.de> |
| In reply to | #400028 |
cross@spitfire.i.gajendra.net (Dan Cross) wrote or quoted:
>I'm not a huge fan of Carruth.
(Text after "| " below was generated by a chatbot asked to explain
narrow contracts and the reduction of efficiency by defining UB.)
(Let me guess: You are not a huge fan of chatbots either!
Ok, that was easy.)
Chandler talked about how narrow contracts allow optimizations.
| - Wide Contract: The function guarantees to handle all possible inputs
| gracefully, usually by returning an error code or throwing an
| exception. (e.g., "If the pointer is null, return ERR_NULL_PTR").
|
| - Narrow Contract: The function only guarantees correct behavior if
| the caller meets specific preconditions. If the preconditions are
| violated, the behavior is undefined.
|
| When is it appropriate to have a narrow contract? Always, when
| performance, memory footprint, or direct hardware control are
| paramount. In operating system kernels, embedded systems, real-time
| applications, and high-performance computing, the overhead of
| validating every pointer, checking every array bound, and verifying
| every integer range is unacceptable. C assumes the programmer is
| competent and knows the state of their own data. Narrow contracts
| shift the burden of correctness from runtime execution to compile-time
| reasoning and programmer discipline.
Chandler also explained how defining UB for certain operations
would require less efficient code to be generated.
| The hardware: Some architectures silently wrap on overflow, some trap
| and halt the CPU, and some have no concept of the operation at all.
| Forcing a single, defined behavior (like "always wrap around") would
| require compilers to insert expensive emulation code on architectures
| that don't support it natively, destroying C's "trust the hardware"
| philosophy.
|
| Or, consider a loop:
|
| for (int i = 0; i < n; i++) {
| arr[i] = 0;
| }
|
| If out-of-bounds array access had defined behavior, the compiler would
| have to insert a bounds check ("if (i >= array_length)") on every single
| iteration. Because out-of-bounds access is UB, the compiler can assume
| n is always within bounds. This allows it to unroll the loop,
| vectorize it using SIMD instructions, and process 8 or 16 elements per
| CPU cycle, yielding massive performance gains.
Well, there are some tests that can be taken out of loops (as
in Java), but other tests can't.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2026-06-14 21:24 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <8_EXR.112952$Mm3.81340@fx33.iad> |
| In reply to | #400051 |
ram@zedat.fu-berlin.de (Stefan Ram) writes: >cross@spitfire.i.gajendra.net (Dan Cross) wrote or quoted: >>I'm not a huge fan of Carruth. > > (Text after "| " below was generated by a chatbot asked to explain > narrow contracts and the reduction of efficiency by defining UB.) > > (Let me guess: You are not a huge fan of chatbots either! > Ok, that was easy.) > > Chandler talked about how narrow contracts allow optimizations. > >| - Wide Contract: The function guarantees to handle all possible inputs >| gracefully, usually by returning an error code or throwing an >| exception. (e.g., "If the pointer is null, return ERR_NULL_PTR"). >| >| - Narrow Contract: The function only guarantees correct behavior if >| the caller meets specific preconditions. If the preconditions are >| violated, the behavior is undefined. >| >| When is it appropriate to have a narrow contract? Always, when >| performance, memory footprint, or direct hardware control are >| paramount. In operating system kernels, embedded systems, real-time >| applications, and high-performance computing, the overhead of >| validating every pointer, checking every array bound, and verifying >| every integer range is unacceptable. I have a recollection that a version of IBM's MVS operating system did, indeed, validate input and output arguments to kernel functions. Indeed, google says it was called MVS/SP and later MVS/XA (extended addressing).
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-15 17:52 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110pe49$5fa$1@reader1.panix.com> |
| In reply to | #400055 |
In article <8_EXR.112952$Mm3.81340@fx33.iad>, Scott Lurndal <slp53@pacbell.net> wrote: >ram@zedat.fu-berlin.de (Stefan Ram) writes: >>cross@spitfire.i.gajendra.net (Dan Cross) wrote or quoted: >>>I'm not a huge fan of Carruth. >> >> (Text after "| " below was generated by a chatbot asked to explain >> narrow contracts and the reduction of efficiency by defining UB.) >> >> (Let me guess: You are not a huge fan of chatbots either! >> Ok, that was easy.) >> >> Chandler talked about how narrow contracts allow optimizations. >> >>| - Wide Contract: The function guarantees to handle all possible inputs >>| gracefully, usually by returning an error code or throwing an >>| exception. (e.g., "If the pointer is null, return ERR_NULL_PTR"). >>| >>| - Narrow Contract: The function only guarantees correct behavior if >>| the caller meets specific preconditions. If the preconditions are >>| violated, the behavior is undefined. >>| >>| When is it appropriate to have a narrow contract? Always, when >>| performance, memory footprint, or direct hardware control are >>| paramount. In operating system kernels, embedded systems, real-time >>| applications, and high-performance computing, the overhead of >>| validating every pointer, checking every array bound, and verifying >>| every integer range is unacceptable. > >I have a recollection that a version of IBM's MVS operating >system did, indeed, validate input and output arguments to kernel >functions. > >Indeed, google says it was called MVS/SP and later MVS/XA (extended addressing). The Midori folks at Microsoft added bounds checking to all array accesses in M# (the safe language they wrote Midori in). They expected performance to be awful; when they provided it, the overhead was pretty much undetectable: the cost was in the noise. - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-06-13 18:32 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110k0mp$329k6$1@dont-email.me> |
| In reply to | #400024 |
On 13/06/2026 14:02, Dan Cross wrote: > In article <110ghmv$21vi3$1@dont-email.me>, > David Brown <david.brown@hesbynett.no> wrote: >> [snip] >> As for my '"modern compilers are evil" crowd' comment, there are people >> (not anyone involved in this discussion) who really do fall into that >> camp. I've seen people who are experienced and respected developers >> make all sorts of accusations to compiler developers, claiming they are >> only interested in high scores on synthetic benchmarks and directly >> insulting their motivations and integrity, blaming them for "breaking" >> their code that relied on the effects of some kinds of UB. It is always >> frustrating when you have code that works fine with one compiler >> version, but using another compiler results in failure due to UB in your >> code - especially if writing correct code gives inefficient results with >> the first compiler. And it's fine to say you'd be happier if a >> particular thing that is UB in C were not UB - but it is unreasonable to >> blame compiler developers for implementing the language as it is defined. > > Eh...I think those people have a point. > > Note, I don't think that "modern compilers are evil" (I mean, > wow, that's a strong word) and I certainly do not think it is > appropriate to malign the people who write them personally over > what one does with code. I think it is important for tools to be helpful, and it's fine to complain if a tool is being directly unhelpful - or ask for improvements when you think it could be better. > > But I _do_ think it is fair to say that UB is very easy to fall > into in C, that programs that have worked correctly (insofar as > their intended behavior as written) for years can suddenly fail > because latent UB is treated differently in a point revision of > a compiler, and that that (as you point out) can be incredibly > frustrating for the authors. It can certainly happen, yes. And I fully sympathise on these few occasions when changes to the standard has meant that code that previously had defined behaviour, now has different or undefined behaviour. (However, I think that for some kinds of code, programmers could be better at specifying exactly what standards their code requires, and the standards they use when compiling code.) But it is important to realise that if you write code with UB, it is /your/ mistake - not the mistake of the compiler developers, or the mistake of the standards authors. Compiler vendors can (and do!) try to help programmers find their mistakes - experience shows, however, that many programmers reach first for bug report forms or complaints in forums before compiler tools like sanitisers or even enabling warnings on their builds. Programming in C is a cooperative effort - including the standards authors, the compiler vendors, and the C programmers. Each group can try to help the others, but each is ultimately responsible for their own part. > > Regehr called out a dichotomy with UB: programmers using a > language hate it; compiler writers love it. I think Regehr has made some good points in his writings, but I do not agree with him on everything. As a programmer, I am a fan of the concept of UB. I am quite happy with the idea that operations have a pre-condition, and that if there is no "right answer" for a given input, I should not provide that input. I prefer that signed integer arithmetic overflow is UB, and do not want it to be wrapping or have some other semantics - to me, it is far clearer that way. If I have UB in my code, it's a bug - no different from any other bug I might make. It is the case that in C, there are some kinds of UB that can be quite subtle. However, you rarely need to risk meeting them. Yes, there are pitfalls - don't go near them, and they don't matter. However, it is unfortunately the case that sometimes avoiding UB can be costly in performance terms. An example would be if you have need of type-punning - perhaps you have a float in memory and you want to access it as an uint32_t for some reason. Casting a float * to an uint32_t * and using that new pointer is UB. Some compilers will nonetheless generate the code you want after such a cast. Some compilers might not, depending on details of the rest of the surrounding code, because it is UB. A non-UB solution would be to use memcpy(), or a type-punning union. For highly optimising compilers, that's fine - the code generated by gcc or clang for a memcpy() here is likely to be as efficient as you could get - directly reading the float from memory to an integer register. For other compilers, however, you might get a call to a memcpy() library function in an external DLL, taking orders of magnitude more cycles. What is the poor programmer to do? Write code that is portable and correct, but very slow with some implementations? Write code that "cheats" and is efficient on some implementations but might not give the desired results on others? Use pre-processor monstrosities to detect different compilers and adapt accordingly? That is what I see as the biggest issue resulting from compiler optimisation based on UB. I don't know what the "best" answer here is. > > Here's my own vignette: I was chatting with a friend who works > on LLVM and clang some time ago. I said, "I don't want UB" and > he replied, "no, you really do." I asked him what he meant and > he responded that I wanted a compiler that is capable of > optimizing my program; "sure, but I still don't want UB." We > went on for a bit, and it became clear that he saw UB as _the_ > vehicle for unlocking optimization. > > I realized that we were not speaking the same language _at all_. > He and I both wanted a language where we could write programs > that yield efficient object code. He saw UB as essential for > that; but what I want is a language with well-defined semantics > that can be aggressively optimized. I too want a language with well-defined semantics that can be aggressively optimised. But I do not see UB as a hinder to that. I am happy knowing that I cannot divide by 0, or find the square root of a negative number (in the real domain). I am happy knowing that I cannot add two ints if their sum overflows the range of their type, and that I cannot call a function with a different number or type of parameters than its definition. I have a great deal of difficulty seeing how things could be any different, other than in a managed language with significant overhead from run-time checks - and that goes against the "aggressively optimised" requirement. Having "well-defined semantics" does not mean the language should accept anything that happens to fit the syntax and grammar rules, or that all functions and operations should give a defined result for all inputs. It means that the set of valid inputs is clearly defined, along with the outputs and effects you get when the inputs are valid. (There are plenty of points in the C standards where the wording could make the semantics clearer, or where the range of input values could easily have been larger - I am not suggesting C is as well-defined as it could reasonably be.) > > That, I think, is the tension: there was a fundamental breakdown > in communication between the users of the language, and those > defining and implementing it. My subjective sense is that in > the past few years things are getting somewhat better, but it is > hard to evolve something as critical and widely used as C. > Communication between the separate parties is always an issue, and it is easy for it to be a one-way street with a language standards committee dictating the rules with little attention to feedback, then compiler vendors following these rules without listening to the users. A challenge here, perhaps, is that users are a very diverse group. How much should compiler vendors cater for those that put a lot of effort into correctness and want top efficiency, or those that are less knowledgable about the language but want to avoid the consequences of their mistakes? What about those working with old code written for different compilers with different unwritten rules? It is not easy to please everyone. >> I am not in any way saying that critics of aspects of C (the language, >> the standards, or compiler implementations) should be dismissed or >> despised - merely that the example of loop elimination leading to UB and >> unexpected results is regularly used as "evidence" by those that hold >> extreme positions about C, despite it being very unrealistic for the >> issue to cause problems in real coding practice. > > The kernel I am working on has about 5 million lines of code. > That code has been evolving for 40 years; some of it predates > the ISO standards and even the ANSI standard. It has been > updated for newer compilers, sure, but in some places the > treatment is surface-level: using ISO-style function prototypes > and definition syntax, for example. But deep problems remain in > parts, and contraints on engineering resources couple with > economic and business pressures so that it's not going to get > cleaned up any time soon. I'm sure there is UB in it; in fact, > I know there is. But them's the breaks; and yet, customers are > using it in production. Because of this, upgrading toolchains > is laborious and complex, and takes a lot of time, and new > compilers are (rightly) viewed with suspicion. That is not a > great situation, but I don't think anyone is angry at the > compiler people over it. I think that is a good way to handle the situation. In my projects, I do not normally upgrade or change toolchains. While I think the risk of UB is small in my own code, small does not mean non-existent. And for my work, generated code that behaves correctly in terms of C semantics but has different execution times or code size might also be an issue - so changes in toolchains mean a lot of extra testing and qualification. In addition, for some microcontrollers the toolchains have relatively small user bases and consequently higher risks of unknown bugs in the toolchains themselves. Sometimes there are also implementation-specific features that change between versions (though that is less of an issue these days). > > And just as it's not acceptable to blame compiler writers for > implementating the language as it is defined, it's not really > acceptable to blame programmers either; some of the people who > put the UB there are (literally) dead, and there's just not > enough time in the day to go clean it all up. I wish there was > more compassion for that. > Being dead does not resolve you of the responsibility - the person that wrote the code with UB is the person who wrote the code with the UB, just like any other bugs. That person wrote the code with the error. It might not be fair to hold it against them - there are a great many possible reasons why it was not their fault (typically management is more at fault than the coders!). And placing blame is rarely a useful exercise - usually it does not matter where the bugs came from, only that they are there and need to be fixed or worked around. > As said earlier, C is what it is. I suspect that it will > continue to make incremental improvements, but we're basically > stuck with what we have. > > - Dan C. > Agreed.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-14 14:33 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110me3t$gli$1@reader1.panix.com> |
| In reply to | #400036 |
In article <110k0mp$329k6$1@dont-email.me>, David Brown <david.brown@hesbynett.no> wrote: >On 13/06/2026 14:02, Dan Cross wrote: >> In article <110ghmv$21vi3$1@dont-email.me>, >> David Brown <david.brown@hesbynett.no> wrote: >>> [snip] >>> As for my '"modern compilers are evil" crowd' comment, there are people >>> (not anyone involved in this discussion) who really do fall into that >>> camp. I've seen people who are experienced and respected developers >>> make all sorts of accusations to compiler developers, claiming they are >>> only interested in high scores on synthetic benchmarks and directly >>> insulting their motivations and integrity, blaming them for "breaking" >>> their code that relied on the effects of some kinds of UB. It is always >>> frustrating when you have code that works fine with one compiler >>> version, but using another compiler results in failure due to UB in your >>> code - especially if writing correct code gives inefficient results with >>> the first compiler. And it's fine to say you'd be happier if a >>> particular thing that is UB in C were not UB - but it is unreasonable to >>> blame compiler developers for implementing the language as it is defined. >> >> Eh...I think those people have a point. >> >> Note, I don't think that "modern compilers are evil" (I mean, >> wow, that's a strong word) and I certainly do not think it is >> appropriate to malign the people who write them personally over >> what one does with code. > >I think it is important for tools to be helpful, and it's fine to >complain if a tool is being directly unhelpful - or ask for improvements >when you think it could be better. Yes. >> But I _do_ think it is fair to say that UB is very easy to fall >> into in C, that programs that have worked correctly (insofar as >> their intended behavior as written) for years can suddenly fail >> because latent UB is treated differently in a point revision of >> a compiler, and that that (as you point out) can be incredibly >> frustrating for the authors. > >It can certainly happen, yes. And I fully sympathise on these few >occasions when changes to the standard has meant that code that >previously had defined behaviour, now has different or undefined >behaviour. (However, I think that for some kinds of code, programmers >could be better at specifying exactly what standards their code >requires, and the standards they use when compiling code.) > >But it is important to realise that if you write code with UB, it is >/your/ mistake - not the mistake of the compiler developers, or the >mistake of the standards authors. Compiler vendors can (and do!) try to >help programmers find their mistakes - experience shows, however, that >many programmers reach first for bug report forms or complaints in >forums before compiler tools like sanitisers or even enabling warnings >on their builds. > >Programming in C is a cooperative effort - including the standards >authors, the compiler vendors, and the C programmers. Each group can >try to help the others, but each is ultimately responsible for their own >part. Here's the problem that I have with this line of reasoning. C is a language that has considerable history; there was a large body of C code written before the first standard was ever created, in 1988; C was a teenager. And it took many years for decent quality ANSI C compilers to be ubiquitous. C could legally drink by then. "Undefined Behavior", in C, in the manner usually discussed in this newsgroup, was introduced with the first standard. That means that there is --- still --- a large body of software that has "UB" that was put there before UB existed as a thing programmers needed to worry about in C. Even once it was a part of C, the concept was communicated poorly. Some people seem to delight in this, believing precision in interpreting the standard in abstruse ways is an expression of deep technical expertise; but it really is not. Yes, UB is created by programmers. However, in large systems, it may be that it was created inadvertantly; someone makes a change that subtley invalidates some invariant that an unknown caller far away in the code base (or in another one that relies on the change via an indirect dependency) and now you've got UB; locally, everything appears correct; but it's the combination where the UB manifests. >> Regehr called out a dichotomy with UB: programmers using a >> language hate it; compiler writers love it. > >I think Regehr has made some good points in his writings, but I do not >agree with him on everything. > >As a programmer, I am a fan of the concept of UB. I am quite happy with >the idea that operations have a pre-condition, and that if there is no >"right answer" for a given input, I should not provide that input. I >prefer that signed integer arithmetic overflow is UB, and do not want it >to be wrapping or have some other semantics - to me, it is far clearer >that way. If I have UB in my code, it's a bug - no different from any >other bug I might make. This example makes little sense to me. If you don't want integer overflow, then don't overflow; the techniques for avoiding it are pretty well known. But why is specifically better that it is UB, rather than than trapping in debug builds, or having IB semantics based on the underlying machine? It seems to be that the burden on the programmer is the same. >It is the case that in C, there are some kinds of UB that can be quite >subtle. However, you rarely need to risk meeting them. Yes, there are >pitfalls - don't go near them, and they don't matter. I disagree. I think almost all non-trivial programs have UB to a greater or lesser extent, whether they intend to or not. >However, it is unfortunately the case that sometimes avoiding UB can be >costly in performance terms. An example would be if you have need of >type-punning - perhaps you have a float in memory and you want to access >it as an uint32_t for some reason. Casting a float * to an uint32_t * >and using that new pointer is UB. Some compilers will nonetheless >generate the code you want after such a cast. Some compilers might not, >depending on details of the rest of the surrounding code, because it is >UB. A non-UB solution would be to use memcpy(), or a type-punning >union. For highly optimising compilers, that's fine - the code >generated by gcc or clang for a memcpy() here is likely to be as >efficient as you could get - directly reading the float from memory to >an integer register. For other compilers, however, you might get a call >to a memcpy() library function in an external DLL, taking orders of >magnitude more cycles. What is the poor programmer to do? Write code >that is portable and correct, but very slow with some implementations? >Write code that "cheats" and is efficient on some implementations but >might not give the desired results on others? Use pre-processor >monstrosities to detect different compilers and adapt accordingly? That >is what I see as the biggest issue resulting from compiler optimisation >based on UB. I don't know what the "best" answer here is. This is kind of my point. If you need a fast way to convery >> Here's my own vignette: I was chatting with a friend who works >> on LLVM and clang some time ago. I said, "I don't want UB" and >> he replied, "no, you really do." I asked him what he meant and >> he responded that I wanted a compiler that is capable of >> optimizing my program; "sure, but I still don't want UB." We >> went on for a bit, and it became clear that he saw UB as _the_ >> vehicle for unlocking optimization. >> >> I realized that we were not speaking the same language _at all_. >> He and I both wanted a language where we could write programs >> that yield efficient object code. He saw UB as essential for >> that; but what I want is a language with well-defined semantics >> that can be aggressively optimized. > >I too want a language with well-defined semantics that can be >aggressively optimised. But I do not see UB as a hinder to that. UB is literally the opposite of well-defined. >I am happy knowing that I cannot divide by 0, Yup. That should be a trap. >or find the square root of a negative number (in the real >domain). Yup. That should be a trap. >I am happy knowing that I cannot add two ints if their sum >overflows the range of their type, Yup. That should be a trap (if you want wrapping semantics, you should request it explicitly). >and that I cannot call a function with a different number or >type of parameters than its definition. Yup. That should be a compile-time error. >I have a great deal of difficulty seeing how things could be >any different, other than in a managed language with significant >overhead from run-time checks - and that goes against the >"aggressively optimised" requirement. There are existence proofs of other languages that can, and do, do these things, and do them well. I hate to keep beating this drum, but I think Rust does well here: in safe Rust, UB is a compile-time error; in *unsafe* Rust, there are tools to help find where programmers violate the language's invariants. >Having "well-defined semantics" does not mean the language should accept >anything that happens to fit the syntax and grammar rules, or that all >functions and operations should give a defined result for all inputs. I never said that it did. >It means that the set of valid inputs is clearly defined, along with the >outputs and effects you get when the inputs are valid. So I was the one who said "well-defined semantics" and I had a specific meaning in mind. Your definition is incomplete with respect to that meaning: in addition to what you said, invalid inputs should be rejected, either as a compile time error, or by generating an exception or panic at runtime. If you want to live dangerously and turn the runtime checks off for performance reasons, then you get 2's complement behavior for integers or whatever the machine does for the others. >(There are plenty of points in the C standards where the wording could >make the semantics clearer, or where the range of input values could >easily have been larger - I am not suggesting C is as well-defined as it >could reasonably be.) It's not just that it's nowhere close to being as well-defined as it should be, it's because the language as defined permits behavior that varies far too widely, specifically because of UB. Consider one of the examples you gave: signed integer overflow. The standard doesn't say that you _can't_ add two numbers together if you overflow, it just says that if you do, the language imposes no requirements on the resulting behavior. It may trap, it may elide the addition entirely, or it may do it and let the result be whatever the underlying machine does. That is, the _language_ does not say that it's a bug; it says that it's not going to say anything about it at all. This is one reason the committee is trying to reign some of this in. >> That, I think, is the tension: there was a fundamental breakdown >> in communication between the users of the language, and those >> defining and implementing it. My subjective sense is that in >> the past few years things are getting somewhat better, but it is >> hard to evolve something as critical and widely used as C. > >Communication between the separate parties is always an issue, and it is >easy for it to be a one-way street with a language standards committee >dictating the rules with little attention to feedback, then compiler >vendors following these rules without listening to the users. > >A challenge here, perhaps, is that users are a very diverse group. How >much should compiler vendors cater for those that put a lot of effort >into correctness and want top efficiency, or those that are less >knowledgable about the language but want to avoid the consequences of >their mistakes? What about those working with old code written for >different compilers with different unwritten rules? It is not easy to >please everyone. I think that's simplistic; not many programmers actively want to "avoid the consequences of their mistakes." Do you really believe that they do? If so, why? Conversely, there *is* this kind of machismo attitude among many C programmers that it requires a superior intellect to truly understand this language, and those who do not (or who make any mistake in their understanding) are simply unworthy. I have repeatedly observed this over many decades now, and when I see it, I think that it is odious. My experience is that most programmers are highly intelligent, capable people. They are not wrong to want behavior they can rely on, particularly when things are not obvious, as they often are not. They also want a language that requires a less lawyerly read of to understand its semantics; that could go the way of formality (my preferred approach) or just clearer exposition. Either would be preferable to the current state. In fairness, I think the current members of the committee recognize this. >>> I am not in any way saying that critics of aspects of C (the language, >>> the standards, or compiler implementations) should be dismissed or >>> despised - merely that the example of loop elimination leading to UB and >>> unexpected results is regularly used as "evidence" by those that hold >>> extreme positions about C, despite it being very unrealistic for the >>> issue to cause problems in real coding practice. >> >> The kernel I am working on has about 5 million lines of code. >> That code has been evolving for 40 years; some of it predates >> the ISO standards and even the ANSI standard. It has been >> updated for newer compilers, sure, but in some places the >> treatment is surface-level: using ISO-style function prototypes >> and definition syntax, for example. But deep problems remain in >> parts, and contraints on engineering resources couple with >> economic and business pressures so that it's not going to get >> cleaned up any time soon. I'm sure there is UB in it; in fact, >> I know there is. But them's the breaks; and yet, customers are >> using it in production. Because of this, upgrading toolchains >> is laborious and complex, and takes a lot of time, and new >> compilers are (rightly) viewed with suspicion. That is not a >> great situation, but I don't think anyone is angry at the >> compiler people over it. > >I think that is a good way to handle the situation. In my projects, I >do not normally upgrade or change toolchains. While I think the risk of >UB is small in my own code, small does not mean non-existent. And for >my work, generated code that behaves correctly in terms of C semantics >but has different execution times or code size might also be an issue - >so changes in toolchains mean a lot of extra testing and qualification. Obviously in a production setting tools should be tested and qualified. But the danger posed by UB adds unacceptable risk on large projects, and the burden for updating a toolchain is too high. That is as much an indictment of the language as of any particular project. As a counter example, there was the Harvey project, which was a fork of Plan 9 where the Plan 9 C dialect was replaced with ISO C; we accounted for this by having CI build with 6 seperate compilers; this flushed out a lot of bugs. I am surprised that more projects do not adopt canary CI builds against newer toolchains. >In addition, for some microcontrollers the toolchains have relatively >small user bases and consequently higher risks of unknown bugs in the >toolchains themselves. Sometimes there are also implementation-specific >features that change between versions (though that is less of an issue >these days). Fun fact: part of the reason Google got involved in clang and LLVM development was because the vendor toolchain for a particular microcontroller used in android phones was buggy and would crash (that is, the compiler itself crashed). The solution was not to live with it; it was to build a better toolchain. Google could afford to do that; I recognize not many organizations can. >> And just as it's not acceptable to blame compiler writers for >> implementating the language as it is defined, it's not really >> acceptable to blame programmers either; some of the people who >> put the UB there are (literally) dead, and there's just not >> enough time in the day to go clean it all up. I wish there was >> more compassion for that. > >Being dead does not resolve you of the responsibility - the person that >wrote the code with UB is the person who wrote the code with the UB, >just like any other bugs. That person wrote the code with the error. See above. Those people may well have written the code before C was standardized and before UB as we know it now existed. Also, by definition UB is not an error. >It might not be fair to hold it against them - there are a great many >possible reasons why it was not their fault (typically management is >more at fault than the coders!). And placing blame is rarely a useful >exercise - usually it does not matter where the bugs came from, only >that they are there and need to be fixed or worked around. Exactly. The footguns hiding in C code that has worked perfectly for decades, dating back to before the standards existed, are legion. Caveat emptor. _Or_ the code may have been written with careful regard for the standard, but something _else_ may have been changed that now leads to exposure to UB. For example, perhaps code was written that multiples two numbers, `a*b`; a known to be `unsigned int` when written, but `b` is a signed int. But maybe that is hidden behind a typedef; some time in the future, the typedef is changed so that `a` is now `unsigned short`; perhaps someone realized that the domain values never exceed 16 bits and by changing the definition some critical structure now fits in a single cache line. But also now the type promotion rules kick so that `a*b` happens with the factors as `signed int` and in there exist values of `a` and `b` where `a*b` overflows: UB. The code had no UB; the change was elsewhere; no one saw this because the tests all passed and everything looked ok; then someone upgrades the compiler and now things break. Who's fault is that? And no, this is not contrived; this is exactly the sort of thing that happens on large, long-lived projects. >> As said earlier, C is what it is. I suspect that it will >> continue to make incremental improvements, but we're basically >> stuck with what we have. > >Agreed. ...but be careful blaming the programmer. - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-06-14 22:02 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110n1db$3sbck$1@dont-email.me> |
| In reply to | #400050 |
On 14/06/2026 16:33, Dan Cross wrote: > In article <110k0mp$329k6$1@dont-email.me>, > David Brown <david.brown@hesbynett.no> wrote: >> On 13/06/2026 14:02, Dan Cross wrote: >>> In article <110ghmv$21vi3$1@dont-email.me>, >>> David Brown <david.brown@hesbynett.no> wrote: >>>> [snip] >>>> As for my '"modern compilers are evil" crowd' comment, there are people >>>> (not anyone involved in this discussion) who really do fall into that >>>> camp. I've seen people who are experienced and respected developers >>>> make all sorts of accusations to compiler developers, claiming they are >>>> only interested in high scores on synthetic benchmarks and directly >>>> insulting their motivations and integrity, blaming them for "breaking" >>>> their code that relied on the effects of some kinds of UB. It is always >>>> frustrating when you have code that works fine with one compiler >>>> version, but using another compiler results in failure due to UB in your >>>> code - especially if writing correct code gives inefficient results with >>>> the first compiler. And it's fine to say you'd be happier if a >>>> particular thing that is UB in C were not UB - but it is unreasonable to >>>> blame compiler developers for implementing the language as it is defined. >>> >>> Eh...I think those people have a point. >>> >>> Note, I don't think that "modern compilers are evil" (I mean, >>> wow, that's a strong word) and I certainly do not think it is >>> appropriate to malign the people who write them personally over >>> what one does with code. >> >> I think it is important for tools to be helpful, and it's fine to >> complain if a tool is being directly unhelpful - or ask for improvements >> when you think it could be better. > > Yes. > >>> But I _do_ think it is fair to say that UB is very easy to fall >>> into in C, that programs that have worked correctly (insofar as >>> their intended behavior as written) for years can suddenly fail >>> because latent UB is treated differently in a point revision of >>> a compiler, and that that (as you point out) can be incredibly >>> frustrating for the authors. >> >> It can certainly happen, yes. And I fully sympathise on these few >> occasions when changes to the standard has meant that code that >> previously had defined behaviour, now has different or undefined >> behaviour. (However, I think that for some kinds of code, programmers >> could be better at specifying exactly what standards their code >> requires, and the standards they use when compiling code.) >> >> But it is important to realise that if you write code with UB, it is >> /your/ mistake - not the mistake of the compiler developers, or the >> mistake of the standards authors. Compiler vendors can (and do!) try to >> help programmers find their mistakes - experience shows, however, that >> many programmers reach first for bug report forms or complaints in >> forums before compiler tools like sanitisers or even enabling warnings >> on their builds. >> >> Programming in C is a cooperative effort - including the standards >> authors, the compiler vendors, and the C programmers. Each group can >> try to help the others, but each is ultimately responsible for their own >> part. > > Here's the problem that I have with this line of reasoning. C > is a language that has considerable history; there was a large > body of C code written before the first standard was ever > created, in 1988; C was a teenager. And it took many years for > decent quality ANSI C compilers to be ubiquitous. C could > legally drink by then. > > "Undefined Behavior", in C, in the manner usually discussed in > this newsgroup, was introduced with the first standard. That > means that there is --- still --- a large body of software that > has "UB" that was put there before UB existed as a thing > programmers needed to worry about in C. > > Even once it was a part of C, the concept was communicated > poorly. > It is certainly the case that C code has been written for a long time. And it is certainly the case that some C code was written long ago, and is still used on systems today. But I think it is important to keep in mind that the solid majority of C code is relatively recent. Very little pre-C90 code is ever compiled with modern tools. Code that is old and still in use is important code, but modern code and modern tools should not be kept back because of it. Maybe there is scope for compilers to have better options for handling old code, other than the usual "Use -O0 to avoid optimising on UB" solution. You could come a long way with a "treat all variables as volatile" flag, for example. > Some people seem to delight in this, believing precision in > interpreting the standard in abstruse ways is an expression of > deep technical expertise; but it really is not. > Agreed. > Yes, UB is created by programmers. However, in large systems, > it may be that it was created inadvertantly; someone makes a > change that subtley invalidates some invariant that an unknown > caller far away in the code base (or in another one that relies > on the change via an indirect dependency) and now you've got UB; > locally, everything appears correct; but it's the combination > where the UB manifests. > That can certainly happen. But that's just bugs in the code. I don't see why UB should be considered as something special here. People making changes to existing code sometimes misunderstand things, or accidentally break something that worked before. That's life as a programmer, and there are techniques to reduce the risk - code reviews, linters, testing regimes, etc. Nothing gives 100% guarantees, and everything has to weigh risks, consequences, costs and resources. UB is not special here. >>> Regehr called out a dichotomy with UB: programmers using a >>> language hate it; compiler writers love it. >> >> I think Regehr has made some good points in his writings, but I do not >> agree with him on everything. >> >> As a programmer, I am a fan of the concept of UB. I am quite happy with >> the idea that operations have a pre-condition, and that if there is no >> "right answer" for a given input, I should not provide that input. I >> prefer that signed integer arithmetic overflow is UB, and do not want it >> to be wrapping or have some other semantics - to me, it is far clearer >> that way. If I have UB in my code, it's a bug - no different from any >> other bug I might make. > > This example makes little sense to me. If you don't want > integer overflow, then don't overflow; the techniques for > avoiding it are pretty well known. But why is specifically > better that it is UB, rather than than trapping in debug > builds, or having IB semantics based on the underlying machine? > It seems to be that the burden on the programmer is the same. > UB means precisely that I can choose trapping, or IB, or optimising on the assumption it does not happen. If signed integer overflow were defined as wrapping, then compilers could not put in traps to catch the errors because as far as the language is concerned, they are not errors. If they are defined as causing traps, then that's the semantics - compilers could not optimise code assuming overflow does not happen, unless it can prove there is no overflow. And making it defined behaviour gives programmers the mistaken idea that they don't need to avoid overflow because there is no UB. Making this UB is an admission of the blindingly obvious - there is no correct answer when signed integer overflow occurs. It tells programmers that it is a mistake to let your arithmetic overflow, and it allows tools to help programmers avoid these mistakes, and it allows compilers to give programmers the most efficient results from known good code rather than adding unnecessary run-time checks that are never triggered. >> It is the case that in C, there are some kinds of UB that can be quite >> subtle. However, you rarely need to risk meeting them. Yes, there are >> pitfalls - don't go near them, and they don't matter. > > I disagree. I think almost all non-trivial programs have UB to > a greater or lesser extent, whether they intend to or not. > >> However, it is unfortunately the case that sometimes avoiding UB can be >> costly in performance terms. An example would be if you have need of >> type-punning - perhaps you have a float in memory and you want to access >> it as an uint32_t for some reason. Casting a float * to an uint32_t * >> and using that new pointer is UB. Some compilers will nonetheless >> generate the code you want after such a cast. Some compilers might not, >> depending on details of the rest of the surrounding code, because it is >> UB. A non-UB solution would be to use memcpy(), or a type-punning >> union. For highly optimising compilers, that's fine - the code >> generated by gcc or clang for a memcpy() here is likely to be as >> efficient as you could get - directly reading the float from memory to >> an integer register. For other compilers, however, you might get a call >> to a memcpy() library function in an external DLL, taking orders of >> magnitude more cycles. What is the poor programmer to do? Write code >> that is portable and correct, but very slow with some implementations? >> Write code that "cheats" and is efficient on some implementations but >> might not give the desired results on others? Use pre-processor >> monstrosities to detect different compilers and adapt accordingly? That >> is what I see as the biggest issue resulting from compiler optimisation >> based on UB. I don't know what the "best" answer here is. > > This is kind of my point. If you need a fast way to convery > (I think you missed a bit of your answer here?) >>> Here's my own vignette: I was chatting with a friend who works >>> on LLVM and clang some time ago. I said, "I don't want UB" and >>> he replied, "no, you really do." I asked him what he meant and >>> he responded that I wanted a compiler that is capable of >>> optimizing my program; "sure, but I still don't want UB." We >>> went on for a bit, and it became clear that he saw UB as _the_ >>> vehicle for unlocking optimization. >>> >>> I realized that we were not speaking the same language _at all_. >>> He and I both wanted a language where we could write programs >>> that yield efficient object code. He saw UB as essential for >>> that; but what I want is a language with well-defined semantics >>> that can be aggressively optimized. >> >> I too want a language with well-defined semantics that can be >> aggressively optimised. But I do not see UB as a hinder to that. > > UB is literally the opposite of well-defined. > I want good definitions of things that should be defined. Things that cannot have good definitions, are fine left undefined. A language standard should not be trying to define the behaviour of /everything/. >> I am happy knowing that I cannot divide by 0, > > Yup. That should be a trap. For some programs, yes. For others, no. > >> or find the square root of a negative number (in the real >> domain). > > Yup. That should be a trap. > For some programs, yes. For others, no. >> I am happy knowing that I cannot add two ints if their sum >> overflows the range of their type, > > Yup. That should be a trap (if you want wrapping semantics, you > should request it explicitly). I agree that wrapping semantics should be something you have to ask for. (As an aside, I think it is a mistake for languages to have types that have wrapping semantics - it's the operations that should wrap, not the types. Zig gets it right by distinguishing between "x + y" and "x +% y".) I don't want to pay the price for checks, traps, and limited re-arrangements and optimisations when I know my expressions don't overflow. But I am also happy to be able to get a trap when I ask for it. > >> and that I cannot call a function with a different number or >> type of parameters than its definition. > > Yup. That should be a compile-time error. > There I agree entirely. The build model of compiling units to separate object files without any information beyond symbol names made sense 50 years ago - we should be doing far better now. (We /can/ do far better, but it requires conventions in the way you write your C code and the options used when compiling or linting the program.) >> I have a great deal of difficulty seeing how things could be >> any different, other than in a managed language with significant >> overhead from run-time checks - and that goes against the >> "aggressively optimised" requirement. > > There are existence proofs of other languages that can, and do, > do these things, and do them well. I hate to keep beating this > drum, but I think Rust does well here: in safe Rust, UB is a > compile-time error; in *unsafe* Rust, there are tools to help > find where programmers violate the language's invariants. > Certainly it is possible to eliminate a number of things that are UB in C. UB that is not necessary, or not useful, is a bad thing in a language. But I think it is equally bad to give things a definition simply to be able to say there is no UB. It is, IMHO, entirely /wrong/ of a language to define integer overflow as wrapping simply so that it is not UB. I do not see a guaranteed incorrect result that likely has catastrophic consequences in a program as being better than UB. (I believe Rust defines integer overflow as trapping in "debug" mode and wrapping in "release" mode, which I think is a horrendous idea.) >> Having "well-defined semantics" does not mean the language should accept >> anything that happens to fit the syntax and grammar rules, or that all >> functions and operations should give a defined result for all inputs. > > I never said that it did. I didn't say you said it did :-) > >> It means that the set of valid inputs is clearly defined, along with the >> outputs and effects you get when the inputs are valid. > > So I was the one who said "well-defined semantics" and I had a > specific meaning in mind. Your definition is incomplete with > respect to that meaning: in addition to what you said, invalid > inputs should be rejected, either as a compile time error, or by > generating an exception or panic at runtime. If you want to > live dangerously and turn the runtime checks off for performance > reasons, then you get 2's complement behavior for integers or > whatever the machine does for the others. > I am all in favour of compile-time checks and rejecting code with errors (not just UB) as soon as possible. The "perfect" language is one where you really can follow the old Ada saying - if you can make it compile, it's ready to ship. I don't live dangerously by not having run-time checks on integer overflows. I make sure my code does not have them, so checks are unnecessary. For some of my code, if it "panicked" somewhere in calculations, that would be a disaster - when you have code controlling power electronics, a sudden stop can mean short-circuits and components releasing their magic grey smoke. Thinking that run-time checks will save you from UB is wishful thinking. How are you going to have run-time checks that a pointer parameter points to a valid object of the right type? You can check for a null-pointer, but that's about it. Some things that are potential UB in C are inherent in the type of language - checking for such problems (at compile-time or run-time) needs a language that has a different way of handling objects and pointers so that you cannot have arbitrary pointers to arbitrary objects. C is not a language suitable for such run-time or compile-time checks - it is a language for getting the highest efficiency because the programmer takes responsibility for getting things right. You are correct that large programs normally have bugs (of which UB is just one class) - the risk of bugs goes up with the size of the code base. The corollary is that C is not a language suitable for large programs. Rust, I think, reduces the risk of some kinds of bugs. So does C++, when used carefully. Most code, however, is best written in languages where these issues cannot occur - or at least where checks can be done without a measurable impact. For example, if you use Python, you never have integer overflow, and you never have invalid pointers. >> (There are plenty of points in the C standards where the wording could >> make the semantics clearer, or where the range of input values could >> easily have been larger - I am not suggesting C is as well-defined as it >> could reasonably be.) > > It's not just that it's nowhere close to being as well-defined > as it should be, it's because the language as defined permits > behavior that varies far too widely, specifically because of UB. > > Consider one of the examples you gave: signed integer overflow. > The standard doesn't say that you _can't_ add two numbers > together if you overflow, it just says that if you do, the > language imposes no requirements on the resulting behavior. It > may trap, it may elide the addition entirely, or it may do it > and let the result be whatever the underlying machine does. > > That is, the _language_ does not say that it's a bug; it says > that it's not going to say anything about it at all. > I'd be happy for the C standard to say that signed integer overflow is a bug, or that code is not allowed to overflow its integer arithmetic. I would not be happy if it said compilers must trap on the bug or handle it in some specific way - what happens when a bug is reached is still UB. And if the wording of the standard were changed to call it a "bug" rather than "UB", it would make absolutely zero difference to the way I write my code. > This is one reason the committee is trying to reign some of this > in. > >>> That, I think, is the tension: there was a fundamental breakdown >>> in communication between the users of the language, and those >>> defining and implementing it. My subjective sense is that in >>> the past few years things are getting somewhat better, but it is >>> hard to evolve something as critical and widely used as C. >> >> Communication between the separate parties is always an issue, and it is >> easy for it to be a one-way street with a language standards committee >> dictating the rules with little attention to feedback, then compiler >> vendors following these rules without listening to the users. >> >> A challenge here, perhaps, is that users are a very diverse group. How >> much should compiler vendors cater for those that put a lot of effort >> into correctness and want top efficiency, or those that are less >> knowledgable about the language but want to avoid the consequences of >> their mistakes? What about those working with old code written for >> different compilers with different unwritten rules? It is not easy to >> please everyone. > > I think that's simplistic; not many programmers actively want to > "avoid the consequences of their mistakes." Do you really > believe that they do? If so, why? It was badly worded - I meant that programmers do not want mistakes that they might make to lead to additional problems. We can all appreciate and expect that if we make a mistake in code with an incorrect calculation, that will give incorrect output, or perhaps a crash in the program. But we hope that it will not lead to corruption of a filesystem, or an exploitable security hole - something out of proportion with the mistake. > > Conversely, there *is* this kind of machismo attitude among many > C programmers that it requires a superior intellect to truly > understand this language, and those who do not (or who make any > mistake in their understanding) are simply unworthy. I have > repeatedly observed this over many decades now, and when I see > it, I think that it is odious. In my field, people usually put a lot of effort into writing code simply and clearly. You avoid mistakes not by being "clever", but by being meticulous and careful. I don't think successful C programming requires greater intellect, knowledge or experience compared to other programming languages - but it /does/ require an appropriate attitude. You are working with sharp knives - pay attention to what you are doing, and you'll be fine. > > My experience is that most programmers are highly intelligent, > capable people. They are not wrong to want behavior they can > rely on, particularly when things are not obvious, as they > often are not. They also want a language that requires a less > lawyerly read of to understand its semantics; that could go the > way of formality (my preferred approach) or just clearer > exposition. Either would be preferable to the current state. > I was avoiding signed integer overflow long before I had read any C standards or even knew about the term "UB". Programming in C does not need a lawyer knowledge of the language. It is just like programming in any other programming language - use features that you know are correct, and if you want to do something and don't know how to do so correctly, look it up. > In fairness, I think the current members of the committee > recognize this. > >>>> I am not in any way saying that critics of aspects of C (the language, >>>> the standards, or compiler implementations) should be dismissed or >>>> despised - merely that the example of loop elimination leading to UB and >>>> unexpected results is regularly used as "evidence" by those that hold >>>> extreme positions about C, despite it being very unrealistic for the >>>> issue to cause problems in real coding practice. >>> >>> The kernel I am working on has about 5 million lines of code. >>> That code has been evolving for 40 years; some of it predates >>> the ISO standards and even the ANSI standard. It has been >>> updated for newer compilers, sure, but in some places the >>> treatment is surface-level: using ISO-style function prototypes >>> and definition syntax, for example. But deep problems remain in >>> parts, and contraints on engineering resources couple with >>> economic and business pressures so that it's not going to get >>> cleaned up any time soon. I'm sure there is UB in it; in fact, >>> I know there is. But them's the breaks; and yet, customers are >>> using it in production. Because of this, upgrading toolchains >>> is laborious and complex, and takes a lot of time, and new >>> compilers are (rightly) viewed with suspicion. That is not a >>> great situation, but I don't think anyone is angry at the >>> compiler people over it. >> >> I think that is a good way to handle the situation. In my projects, I >> do not normally upgrade or change toolchains. While I think the risk of >> UB is small in my own code, small does not mean non-existent. And for >> my work, generated code that behaves correctly in terms of C semantics >> but has different execution times or code size might also be an issue - >> so changes in toolchains mean a lot of extra testing and qualification. > > Obviously in a production setting tools should be tested and > qualified. But the danger posed by UB adds unacceptable risk on > large projects, and the burden for updating a toolchain is too > high. That is as much an indictment of the language as of any > particular project. > > As a counter example, there was the Harvey project, which was a > fork of Plan 9 where the Plan 9 C dialect was replaced with ISO > C; we accounted for this by having CI build with 6 seperate > compilers; this flushed out a lot of bugs. > > I am surprised that more projects do not adopt canary CI builds > against newer toolchains. > >> In addition, for some microcontrollers the toolchains have relatively >> small user bases and consequently higher risks of unknown bugs in the >> toolchains themselves. Sometimes there are also implementation-specific >> features that change between versions (though that is less of an issue >> these days). > > Fun fact: part of the reason Google got involved in clang and > LLVM development was because the vendor toolchain for a > particular microcontroller used in android phones was buggy and > would crash (that is, the compiler itself crashed). The > solution was not to live with it; it was to build a better > toolchain. > Buggy toolchains are always a pain. (So is buggy hardware - microcontrollers and cpus have their errors too.) > Google could afford to do that; I recognize not many > organizations can. Unfortunately that's true. > >>> And just as it's not acceptable to blame compiler writers for >>> implementating the language as it is defined, it's not really >>> acceptable to blame programmers either; some of the people who >>> put the UB there are (literally) dead, and there's just not >>> enough time in the day to go clean it all up. I wish there was >>> more compassion for that. >> >> Being dead does not resolve you of the responsibility - the person that >> wrote the code with UB is the person who wrote the code with the UB, >> just like any other bugs. That person wrote the code with the error. > > See above. Those people may well have written the code before C > was standardized and before UB as we know it now existed. Also, > by definition UB is not an error. > >> It might not be fair to hold it against them - there are a great many >> possible reasons why it was not their fault (typically management is >> more at fault than the coders!). And placing blame is rarely a useful >> exercise - usually it does not matter where the bugs came from, only >> that they are there and need to be fixed or worked around. > > Exactly. The footguns hiding in C code that has worked > perfectly for decades, dating back to before the standards > existed, are legion. Caveat emptor. > > _Or_ the code may have been written with careful regard for the > standard, but something _else_ may have been changed that now > leads to exposure to UB. For example, perhaps code was written > that multiples two numbers, `a*b`; a known to be `unsigned int` > when written, but `b` is a signed int. But maybe that is hidden > behind a typedef; some time in the future, the typedef is > changed so that `a` is now `unsigned short`; perhaps someone > realized that the domain values never exceed 16 bits and by > changing the definition some critical structure now fits in a > single cache line. But also now the type promotion rules kick > so that `a*b` happens with the factors as `signed int` and in > there exist values of `a` and `b` where `a*b` overflows: UB. > > The code had no UB; the change was elsewhere; no one saw this > because the tests all passed and everything looked ok; then > someone upgrades the compiler and now things break. > > Who's fault is that? There's no simple answer here. But one thing is clear to me - "UB" is irrelevant here (and in many of your points). It would not matter if everything had fully defined behaviour. The point is that something is changed in one part of the code that has unexpected consequences in another part of the code. Who cares if there is UB or not? The issue is that the code does not work as intended or expected. UB can provide situations where you have unexpected bugs - but so can all sorts of other things. > > And no, this is not contrived; this is exactly the sort of thing > that happens on large, long-lived projects. > >>> As said earlier, C is what it is. I suspect that it will >>> continue to make incremental improvements, but we're basically >>> stuck with what we have. >> >> Agreed. > > ...but be careful blaming the programmer. > Or the language, or the tools.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-06-14 15:55 -0700 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110nbge$3uv6b$1@kst.eternal-september.org> |
| In reply to | #400053 |
David Brown <david.brown@hesbynett.no> writes:
[...]
> UB means precisely that I can choose trapping, or IB, or optimising on
> the assumption it does not happen.
No, it means that the implementation can make that choice (or allow you
to make that choice). A conforming compiler could generate code on the
assumption that signed overflow never happens, and not give the
programmer any options.
[...]
> Making this UB is an admission of the blindingly obvious - there is no
> correct answer when signed integer overflow occurs. It tells
> programmers that it is a mistake to let your arithmetic overflow, and
> it allows tools to help programmers avoid these mistakes, and it
> allows compilers to give programmers the most efficient results from
> known good code rather than adding unnecessary run-time checks that
> are never triggered.
Trapping or raising/throwing an exception on overflow would also be an
admission of the blindingly obvious. And a sufficiently clever compiler
can omit some (not all) checks in cases where it can be statically
proved that overflow doesn't occur, and/or hoist some checks out of
loops.
Of course those kinds of checks are not in the "spirit of C".
[...]
>>> I am happy knowing that I cannot divide by 0,
>> Yup. That should be a trap.
>
> For some programs, yes. For others, no.
What's the difference between these programs?
[...]
> I don't want to pay the price for checks, traps, and limited
> re-arrangements and optimisations when I know my expressions don't
> overflow. But I am also happy to be able to get a trap when I ask for
> it.
I don't want to pay the price of checking for syntax errors when I know
my code is syntactically correct. But I never know that, because I'm
fallible.
I admit that's not a very strong argument. There are real differences
between compile-time and run-time checks.
[...]
--
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-06-15 10:09 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110oc0k$6rfi$1@dont-email.me> |
| In reply to | #400057 |
On 15/06/2026 00:55, Keith Thompson wrote: > David Brown <david.brown@hesbynett.no> writes: > [...] >> UB means precisely that I can choose trapping, or IB, or optimising on >> the assumption it does not happen. > > No, it means that the implementation can make that choice (or allow you > to make that choice). A conforming compiler could generate code on the > assumption that signed overflow never happens, and not give the > programmer any options. Sure. But if it were not UB, then a conforming implementation could not make such choices or give me such choices. UB does not mean that I definitely have such choices (as my poor wording implies), but that implementations are able to give me the choice. If the standards had said integer overflow was IB, then that puts limits on what the compiler can do - and therefore on what it can do to help the programmer. Exactly what options it had would depend on the wording of the standard, such as whether it required an "implementation-defined value" or, like narrowing conversions to signed integer types, "either the result is implementation-defined or an implementation-defined signal is raised". However, even in that later case I think it would be more confusing for a lot of programmers - many programmers, quite reasonably, have an intuition that "UB" means "don't do this" or "this is not legal in C". They also have the intuition that "IB" means "this works according to the underlying hardware". If the standards had said integer overflow was IB, most programmers would immediately assume that meant wrapping behaviour. More interesting, I think, is the possible future "erroneous behaviour" marker. My understanding is that it lets the compiler have traps or other run-time detection, or provide unspecified values, while making it clear that erroneous behaviour is a result of software bugs. > > [...] > >> Making this UB is an admission of the blindingly obvious - there is no >> correct answer when signed integer overflow occurs. It tells >> programmers that it is a mistake to let your arithmetic overflow, and >> it allows tools to help programmers avoid these mistakes, and it >> allows compilers to give programmers the most efficient results from >> known good code rather than adding unnecessary run-time checks that >> are never triggered. > > Trapping or raising/throwing an exception on overflow would also be an > admission of the blindingly obvious. It is obvious - to me, anyway - that signed overflow is a mistake in the code. It is trying to do something that cannot be done. What is the single-digit sum of 5 and 8? There is no answer. The answer is not 3, or 9. Putting your hand in the air and asking the teacher for help might be appropriate sometimes, but it is not a correct answer. Throwing some kind of exception or trap can definitely be helpful at times. And I agree that it would make it obvious that there has been a problem detected. But throwing exceptions or traps can cause more problems (the Ariane 5 failure was caused by the exception handler, not the overflow fault). That does not mean it is better to ignore overflows - it means there is no appropriate action that is suitable in every situation. I am far from convinced that there is even a reasonable choice of default action that could be usefully made. > And a sufficiently clever compiler > can omit some (not all) checks in cases where it can be statically > proved that overflow doesn't occur, and/or hoist some checks out of > loops. Sure - but in practice having strict overflow checks would significantly reduce optimisation and re-arrangement possibilities, as well as having to include the checks themselves. You might allow non-strict checks in some manner (thus allowing optimisations like "a + b - a" reducing to just "b"), but I think that might be hard to specify and would reduce the debugging help of the checks. > > Of course those kinds of checks are not in the "spirit of C". > Indeed. And if we want to move away from the "spirit of C", then I think we should move away from the /language/ of C. In C, people do not expect exceptions or sudden jumps from their code - they expect that if there is checking for errors, it is explicit in the code. In many other languages, there is a much clearer understanding that lots of things can fail and cause immediate exits from the function - and code is (hopefully!) written to handle that. > [...] > >>>> I am happy knowing that I cannot divide by 0, >>> Yup. That should be a trap. >> >> For some programs, yes. For others, no. > > What's the difference between these programs? There are disadvantages in having a trap. It can (depending on hardware) mean extra code to detect the zero - usually that run-time cost is negligible, but sometimes it is not. It will mean extra code to handle the exception - again, often but not always negligible. Those costs apply even if the programmer has made sure that division by zero never occurs. And if a trap is thrown, what then? I think that a programmer that is careful enough to see that a division expression might throw, and handle the trap or exception appropriately, is going to be careful enough to avoid the problem in the first place. So the trap is going to be unexpected and handled badly. A badly handled division by zero exception left the USS Yorktown dead in the water for three hours. Is it better /not/ to trap? There is no general rule. If you have tried to divide by zero, something has gone wrong before the division, and there are no good answers to what will go wrong afterwards. Sometimes it is possible to do damage limitation - sometimes not. The correct way to handle the situation is to avoid it - be sure that you are not dividing by zero in the first place. Identify and handle the problem where it occurs - when this zero is created, or the circumstances leading to that point - rather than trying to do a post-mortem after the failed division. And if you are doing that, then what benefit is there in having trapping for division by zero? It becomes just a waste of effort. (There are other ways of handling such things, like the use of NaN's in floating point, or extending your integers with some kind of "invalid" indicators.) > > [...] > >> I don't want to pay the price for checks, traps, and limited >> re-arrangements and optimisations when I know my expressions don't >> overflow. But I am also happy to be able to get a trap when I ask for >> it. > > I don't want to pay the price of checking for syntax errors when I know > my code is syntactically correct. But I never know that, because I'm > fallible. > Checking for syntax errors is cheap - PC computing power is, in this context, pretty much free and unlimited. If I am using a target environment where run-time resources are plentiful, I would not be using C in the first place. > I admit that's not a very strong argument. There are real differences > between compile-time and run-time checks. > Perhaps I work in a field where that difference is more extreme than for many programmers, and I thus feel it more than most.
[toc] | [prev] | [next] | [standalone]
| From | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-06-15 10:43 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110ol0b$2gc9c$1@paganini.bofh.team> |
| In reply to | #400061 |
David Brown <david.brown@hesbynett.no> wrote:
> On 15/06/2026 00:55, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
<snip>
>> [...]
>>> Making this UB is an admission of the blindingly obvious - there is no
>>> correct answer when signed integer overflow occurs. It tells
>>> programmers that it is a mistake to let your arithmetic overflow, and
>>> it allows tools to help programmers avoid these mistakes, and it
>>> allows compilers to give programmers the most efficient results from
>>> known good code rather than adding unnecessary run-time checks that
>>> are never triggered.
>>
>> Trapping or raising/throwing an exception on overflow would also be an
>> admission of the blindingly obvious.
>
> It is obvious - to me, anyway - that signed overflow is a mistake in the
> code. It is trying to do something that cannot be done. What is the
> single-digit sum of 5 and 8? There is no answer. The answer is not 3,
> or 9. Putting your hand in the air and asking the teacher for help
> might be appropriate sometimes, but it is not a correct answer.
>
> Throwing some kind of exception or trap can definitely be helpful at
> times. And I agree that it would make it obvious that there has been a
> problem detected. But throwing exceptions or traps can cause more
> problems (the Ariane 5 failure was caused by the exception handler, not
> the overflow fault). That does not mean it is better to ignore
> overflows - it means there is no appropriate action that is suitable in
> every situation. I am far from convinced that there is even a
> reasonable choice of default action that could be usefully made.
>
>
>> And a sufficiently clever compiler
>> can omit some (not all) checks in cases where it can be statically
>> proved that overflow doesn't occur, and/or hoist some checks out of
>> loops.
>
> Sure - but in practice having strict overflow checks would significantly
> reduce optimisation and re-arrangement possibilities, as well as having
> to include the checks themselves. You might allow non-strict checks in
> some manner (thus allowing optimisations like "a + b - a" reducing to
> just "b"), but I think that might be hard to specify and would reduce
> the debugging help of the checks.
IMO resonable and easy definition is: computation either delivers
mathematically correct result or traps, and it is not allowed to
trap in cases where naive bottom-up evaluation does not trap.
In more formal way optimization is not allowed to introduce
stronger precondition, but may weaken it.
<snip>
> The correct way to handle the situation is to avoid it - be sure that
> you are not dividing by zero in the first place. Identify and handle
> the problem where it occurs - when this zero is created, or the
> circumstances leading to that point - rather than trying to do a
> post-mortem after the failed division. And if you are doing that, then
> what benefit is there in having trapping for division by zero? It
> becomes just a waste of effort.
What is value of certification required for some software? If
programmer did good job then program will work correctly.
Trap give assurance that programmer indeed correctly handled
tricky problem. And once you know that computation works
according to math rules other forms of verification are easier.
You also seem to have bias to real time control: if you need
value just at given moment, then it is hard to do something
reasonable. But at least in some control areas there is
notion of "safe state", for example working heavy machine
is dangerous, stopped one usually is considerd safe. If
there is safe state, then anything not expected by program
should trigger transition to safe state.
In general computation, if you need correct value and have some
time there are options which may involve re-doing computation at
higher precistion, which may get rid of occasional overflows
and divisions by zero due to overflow. Division by zero may
be due to bad input data, traps allow indentification of
such data (doing it in other way may be computationaly quite
expensive).
--
Waldek Hebisch
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-06-15 16:01 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110p0js$d5lu$1@dont-email.me> |
| In reply to | #400067 |
On 15/06/2026 12:43, Waldek Hebisch wrote: > David Brown <david.brown@hesbynett.no> wrote: >> On 15/06/2026 00:55, Keith Thompson wrote: >>> David Brown <david.brown@hesbynett.no> writes: > <snip> >>> [...] >>>> Making this UB is an admission of the blindingly obvious - there is no >>>> correct answer when signed integer overflow occurs. It tells >>>> programmers that it is a mistake to let your arithmetic overflow, and >>>> it allows tools to help programmers avoid these mistakes, and it >>>> allows compilers to give programmers the most efficient results from >>>> known good code rather than adding unnecessary run-time checks that >>>> are never triggered. >>> >>> Trapping or raising/throwing an exception on overflow would also be an >>> admission of the blindingly obvious. >> >> It is obvious - to me, anyway - that signed overflow is a mistake in the >> code. It is trying to do something that cannot be done. What is the >> single-digit sum of 5 and 8? There is no answer. The answer is not 3, >> or 9. Putting your hand in the air and asking the teacher for help >> might be appropriate sometimes, but it is not a correct answer. >> >> Throwing some kind of exception or trap can definitely be helpful at >> times. And I agree that it would make it obvious that there has been a >> problem detected. But throwing exceptions or traps can cause more >> problems (the Ariane 5 failure was caused by the exception handler, not >> the overflow fault). That does not mean it is better to ignore >> overflows - it means there is no appropriate action that is suitable in >> every situation. I am far from convinced that there is even a >> reasonable choice of default action that could be usefully made. >> >> >>> And a sufficiently clever compiler >>> can omit some (not all) checks in cases where it can be statically >>> proved that overflow doesn't occur, and/or hoist some checks out of >>> loops. >> >> Sure - but in practice having strict overflow checks would significantly >> reduce optimisation and re-arrangement possibilities, as well as having >> to include the checks themselves. You might allow non-strict checks in >> some manner (thus allowing optimisations like "a + b - a" reducing to >> just "b"), but I think that might be hard to specify and would reduce >> the debugging help of the checks. > > IMO resonable and easy definition is: computation either delivers > mathematically correct result or traps, and it is not allowed to > trap in cases where naive bottom-up evaluation does not trap. > In more formal way optimization is not allowed to introduce > stronger precondition, but may weaken it. > It is always the case that an implementation can weaken preconditions and strengthen postconditions and remain correct - though it might then be less efficient than you expect. But if you are /requiring/ a weaker precondition and /requiring/ a strong postcondition - such as by insisting on traps on overflow - you are changing the function or operation specification, and it is not necessarily a good thing. In C, the integer addition operation "c = a + b;" has a precondition : (a + b) <= INT_MAX, (a + b) >= INT_MIN It has the postcondition : c == a + b Saying that it must trap if there is overflow weakens the precondition to any "a" and "b", but makes the postcondition much more complicated. It means it is no longer true that the result of an addition operation is the sum of the operands. Addition is no longer a "pure" function - now it has side-effects that are completely unpredictable at the site of use. Programmers can no longer rely on the timing of the operation, stack usage, interaction with other code, or even that the operation ever finishes. If your code is correct, and overflow never happens, then this is all a big disadvantage in terms of understanding and analysing the code. And it does not in any way reduce the effort needed to be sure that your inputs are appropriate for getting the desired results of the operation. Trapping like this can certainly be useful for debugging. But as a general feature it gives a false sense of security, complicates mathematical analysis, introduces massive additional possible code path choices which are either real or almost certainly untested in practice, or not real (because the compiler can see they are not taken) and untestable. That is not qualitatively worse than "who knows what will happen" UB, but it is not significantly better. > <snip> > >> The correct way to handle the situation is to avoid it - be sure that >> you are not dividing by zero in the first place. Identify and handle >> the problem where it occurs - when this zero is created, or the >> circumstances leading to that point - rather than trying to do a >> post-mortem after the failed division. And if you are doing that, then >> what benefit is there in having trapping for division by zero? It >> becomes just a waste of effort. > > What is value of certification required for some software? If > programmer did good job then program will work correctly. Yes. > Trap give assurance that programmer indeed correctly handled > tricky problem. No, it certainly does not. And one of the reasons to dislike traps is that it makes people think like that. A trap can only happen if the programmer did /not/ handle the problem correctly. And I expect that if the programmer is able to write an appropriate specific trap handler for the failing expression (rather than a program-global "crash with error message" handler), then he/she would be able to avoid the problem in the first place. Sometimes, of course, you are trying to write code that has some input which is supposed to be correct, but you are not sure - and you can't change the calling code. How you handle that situation will depend on the program and the situation. But I don't see trapping as "correct handling" unless the whole program is written with the expectation of traps for error handling. You might, however, end up deciding that trapping is the least bad option. > And once you know that computation works > according to math rules other forms of verification are easier. > > You also seem to have bias to real time control: if you need > value just at given moment, then it is hard to do something > reasonable. But at least in some control areas there is > notion of "safe state", for example working heavy machine > is dangerous, stopped one usually is considerd safe. If > there is safe state, then anything not expected by program > should trigger transition to safe state. I think if you are /not/ concerned with high efficiency in the code, then you should be seriously questioning the choice of C as the language in the first place. And even if you use C, there are often things you can do to avoid having problems in the first place. The obvious one for integer overflow is to make more use of bigger types. > > In general computation, if you need correct value and have some > time there are options which may involve re-doing computation at > higher precistion, which may get rid of occasional overflows > and divisions by zero due to overflow. Division by zero may > be due to bad input data, traps allow indentification of > such data (doing it in other way may be computationaly quite > expensive). >
[toc] | [prev] | [next] | [standalone]
| From | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-06-15 17:57 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110pee9$2icnv$1@paganini.bofh.team> |
| In reply to | #400069 |
David Brown <david.brown@hesbynett.no> wrote:
> On 15/06/2026 12:43, Waldek Hebisch wrote:
>> David Brown <david.brown@hesbynett.no> wrote:
>>> On 15/06/2026 00:55, Keith Thompson wrote:
>>>> David Brown <david.brown@hesbynett.no> writes:
>> <snip>
>>>> [...]
>>>>> Making this UB is an admission of the blindingly obvious - there is no
>>>>> correct answer when signed integer overflow occurs. It tells
>>>>> programmers that it is a mistake to let your arithmetic overflow, and
>>>>> it allows tools to help programmers avoid these mistakes, and it
>>>>> allows compilers to give programmers the most efficient results from
>>>>> known good code rather than adding unnecessary run-time checks that
>>>>> are never triggered.
>>>>
>>>> Trapping or raising/throwing an exception on overflow would also be an
>>>> admission of the blindingly obvious.
>>>
>>> It is obvious - to me, anyway - that signed overflow is a mistake in the
>>> code. It is trying to do something that cannot be done. What is the
>>> single-digit sum of 5 and 8? There is no answer. The answer is not 3,
>>> or 9. Putting your hand in the air and asking the teacher for help
>>> might be appropriate sometimes, but it is not a correct answer.
>>>
>>> Throwing some kind of exception or trap can definitely be helpful at
>>> times. And I agree that it would make it obvious that there has been a
>>> problem detected. But throwing exceptions or traps can cause more
>>> problems (the Ariane 5 failure was caused by the exception handler, not
>>> the overflow fault). That does not mean it is better to ignore
>>> overflows - it means there is no appropriate action that is suitable in
>>> every situation. I am far from convinced that there is even a
>>> reasonable choice of default action that could be usefully made.
>>>
>>>
>>>> And a sufficiently clever compiler
>>>> can omit some (not all) checks in cases where it can be statically
>>>> proved that overflow doesn't occur, and/or hoist some checks out of
>>>> loops.
>>>
>>> Sure - but in practice having strict overflow checks would significantly
>>> reduce optimisation and re-arrangement possibilities, as well as having
>>> to include the checks themselves. You might allow non-strict checks in
>>> some manner (thus allowing optimisations like "a + b - a" reducing to
>>> just "b"), but I think that might be hard to specify and would reduce
>>> the debugging help of the checks.
>>
>> IMO resonable and easy definition is: computation either delivers
>> mathematically correct result or traps, and it is not allowed to
>> trap in cases where naive bottom-up evaluation does not trap.
>> In more formal way optimization is not allowed to introduce
>> stronger precondition, but may weaken it.
>>
>
> It is always the case that an implementation can weaken preconditions
> and strengthen postconditions and remain correct - though it might then
> be less efficient than you expect. But if you are /requiring/ a weaker
> precondition and /requiring/ a strong postcondition - such as by
> insisting on traps on overflow - you are changing the function or
> operation specification, and it is not necessarily a good thing.
>
> In C, the integer addition operation "c = a + b;" has a precondition :
>
> (a + b) <= INT_MAX, (a + b) >= INT_MIN
>
> It has the postcondition :
>
> c == a + b
>
> Saying that it must trap if there is overflow weakens the precondition
> to any "a" and "b", but makes the postcondition much more complicated.
No. Precondition is the same. Postcondition has additional term
"computation finished with no traps".
> It means it is no longer true that the result of an addition operation
> is the sum of the operands.
Oposite of that: no traps means that regardless of precondition
the result of an addition operation is the sum of the operands.
> Addition is no longer a "pure" function -
> now it has side-effects that are completely unpredictable at the site of
> use. Programmers can no longer rely on the timing of the operation,
> stack usage, interaction with other code, or even that the operation
> ever finishes.
The difference is that without traps programmers do not know if
arithmetic operations give correct result. With traps they do
not know if program will successfully finish, but if it
finishes they know that arithmetic gave correct results.
> If your code is correct, and overflow never happens, then this is all a
> big disadvantage in terms of understanding and analysing the code. And
> it does not in any way reduce the effort needed to be sure that your
> inputs are appropriate for getting the desired results of the operation.
One needs to use correct formulas, there is no way around that.
Without traps programmer must analyse ranges of all intermetiate
expressions. That is tedious and error prone. People work
around that by activating traps during testing, but it is
quite hard to find worst case values, so errors may be
easily missed during testing. Having traps active during
production runs means that you may discover problem. You
apparently think that ignoring possible problems at
runtime is good thing. For simple programs you may analyze
it well enough to be sure that nothing bad happens at
runtime, but in general computing we use a lot of "interesting"
programs which are too complex to analyse. We hope that
they will run OK, but have no proof. Sometimes hope is
based on statistical tests and on low probability input
program may fail. Traps are useful to make sure that
wrong results will not propagate further.
> Trapping like this can certainly be useful for debugging. But as a
> general feature it gives a false sense of security, complicates
> mathematical analysis, introduces massive additional possible code path
> choices which are either real or almost certainly untested in practice,
> or not real (because the compiler can see they are not taken) and
> untestable.
You get extra code paths only if you attempt to handle traps.
Trapping of overflows gives you assurance that in computation that
you did and which finished with no traps there were no errors of
certain kind (that is wrong results due to overflow). That is
really not different than insistence on static types. Neither
assures you of no bugs, but each tells you that some bugs
did not happen. Of course, trapping at runtime is less
satisfactory than compile time checking, but tight a priori
bounds on ranges are notoriusly hard to obtain, so trapping
is the best we can have for high performance software with
current state of art.
> That is not qualitatively worse than "who knows what will
> happen" UB, but it is not significantly better.
>
>
>> <snip>
>>
>>> The correct way to handle the situation is to avoid it - be sure that
>>> you are not dividing by zero in the first place. Identify and handle
>>> the problem where it occurs - when this zero is created, or the
>>> circumstances leading to that point - rather than trying to do a
>>> post-mortem after the failed division. And if you are doing that, then
>>> what benefit is there in having trapping for division by zero? It
>>> becomes just a waste of effort.
>>
>> What is value of certification required for some software? If
>> programmer did good job then program will work correctly.
>
> Yes.
>
>> Trap give assurance that programmer indeed correctly handled
>> tricky problem.
>
> No, it certainly does not. And one of the reasons to dislike traps is
> that it makes people think like that. A trap can only happen if the
> programmer did /not/ handle the problem correctly.
Yes.
> And I expect that if
> the programmer is able to write an appropriate specific trap handler for
> the failing expression (rather than a program-global "crash with error
> message" handler), then he/she would be able to avoid the problem in the
> first place.
Rather non-specific trap handler could work as "redo the computation
in arbitrary precision". If problem (like division by zero) persists,
then there is logic bug, otherwise it means that precision was
inadequate and problem is resolved.
Howver, you should think about such traps similarly to parity error
which can be signaled by some hardware. There is low but nonzero
probablity that such error can occur. Parity check gives you
reasonable chance to detect it. Handling is at least as problematic
as with overflow. Absence of traps gives you less info: no
overflow traps mean no overflow, no parity traps means that
parity was correct, but intent of parity check it to discover bit
error and they are possible even with correct parity. So, do you
think that parity check inside MCU-s are useless?
> Sometimes, of course, you are trying to write code that has some input
> which is supposed to be correct, but you are not sure - and you can't
> change the calling code. How you handle that situation will depend on
> the program and the situation. But I don't see trapping as "correct
> handling" unless the whole program is written with the expectation of
> traps for error handling. You might, however, end up deciding that
> trapping is the least bad option.
>
>
>> And once you know that computation works
>> according to math rules other forms of verification are easier.
>>
>> You also seem to have bias to real time control: if you need
>> value just at given moment, then it is hard to do something
>> reasonable. But at least in some control areas there is
>> notion of "safe state", for example working heavy machine
>> is dangerous, stopped one usually is considerd safe. If
>> there is safe state, then anything not expected by program
>> should trigger transition to safe state.
>
> I think if you are /not/ concerned with high efficiency in the code,
Well, if efficiency does not matter traps can be implemented as
a software layer above the language. Or one can use arbitrary
precision arithmetic. Traps matter when efficiency matters,
so they should be implemented in place giving best efficiency,
at best in CPU and if that is not possible then in optimizing
compiler.
> then you should be seriously questioning the choice of C as the language
> in the first place. And even if you use C, there are often things you
> can do to avoid having problems in the first place. The obvious one for
> integer overflow is to make more use of bigger types.
Which may be best choice if efficiency is not important. But
some calculations require surprisingly large accuracy to avoid
overflow. Worse, in vast majority of cases lower accuracy
may be adequate, so there is pressure to use "sufficient"
accuracy overlooking special cases.
>> In general computation, if you need correct value and have some
>> time there are options which may involve re-doing computation at
>> higher precistion, which may get rid of occasional overflows
>> and divisions by zero due to overflow. Division by zero may
>> be due to bad input data, traps allow indentification of
>> such data (doing it in other way may be computationaly quite
>> expensive).
>>
>
--
Waldek Hebisch
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-06-16 10:10 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110r0dd$tng9$1@dont-email.me> |
| In reply to | #400071 |
On 15/06/2026 19:57, Waldek Hebisch wrote: > David Brown <david.brown@hesbynett.no> wrote: >> On 15/06/2026 12:43, Waldek Hebisch wrote: >>> David Brown <david.brown@hesbynett.no> wrote: >>>> On 15/06/2026 00:55, Keith Thompson wrote: >>>>> David Brown <david.brown@hesbynett.no> writes: >>> <snip> >>>>> [...] >>>>>> Making this UB is an admission of the blindingly obvious - there is no >>>>>> correct answer when signed integer overflow occurs. It tells >>>>>> programmers that it is a mistake to let your arithmetic overflow, and >>>>>> it allows tools to help programmers avoid these mistakes, and it >>>>>> allows compilers to give programmers the most efficient results from >>>>>> known good code rather than adding unnecessary run-time checks that >>>>>> are never triggered. >>>>> >>>>> Trapping or raising/throwing an exception on overflow would also be an >>>>> admission of the blindingly obvious. >>>> >>>> It is obvious - to me, anyway - that signed overflow is a mistake in the >>>> code. It is trying to do something that cannot be done. What is the >>>> single-digit sum of 5 and 8? There is no answer. The answer is not 3, >>>> or 9. Putting your hand in the air and asking the teacher for help >>>> might be appropriate sometimes, but it is not a correct answer. >>>> >>>> Throwing some kind of exception or trap can definitely be helpful at >>>> times. And I agree that it would make it obvious that there has been a >>>> problem detected. But throwing exceptions or traps can cause more >>>> problems (the Ariane 5 failure was caused by the exception handler, not >>>> the overflow fault). That does not mean it is better to ignore >>>> overflows - it means there is no appropriate action that is suitable in >>>> every situation. I am far from convinced that there is even a >>>> reasonable choice of default action that could be usefully made. >>>> >>>> >>>>> And a sufficiently clever compiler >>>>> can omit some (not all) checks in cases where it can be statically >>>>> proved that overflow doesn't occur, and/or hoist some checks out of >>>>> loops. >>>> >>>> Sure - but in practice having strict overflow checks would significantly >>>> reduce optimisation and re-arrangement possibilities, as well as having >>>> to include the checks themselves. You might allow non-strict checks in >>>> some manner (thus allowing optimisations like "a + b - a" reducing to >>>> just "b"), but I think that might be hard to specify and would reduce >>>> the debugging help of the checks. >>> >>> IMO resonable and easy definition is: computation either delivers >>> mathematically correct result or traps, and it is not allowed to >>> trap in cases where naive bottom-up evaluation does not trap. >>> In more formal way optimization is not allowed to introduce >>> stronger precondition, but may weaken it. >>> >> >> It is always the case that an implementation can weaken preconditions >> and strengthen postconditions and remain correct - though it might then >> be less efficient than you expect. But if you are /requiring/ a weaker >> precondition and /requiring/ a strong postcondition - such as by >> insisting on traps on overflow - you are changing the function or >> operation specification, and it is not necessarily a good thing. >> >> In C, the integer addition operation "c = a + b;" has a precondition : >> >> (a + b) <= INT_MAX, (a + b) >= INT_MIN >> >> It has the postcondition : >> >> c == a + b >> >> Saying that it must trap if there is overflow weakens the precondition >> to any "a" and "b", but makes the postcondition much more complicated. > > No. Precondition is the same. Postcondition has additional term > "computation finished with no traps". That's back where we started, with no defined behaviour if "a + b" is too big - that is the specification for normal C addition. When you say that addition should either deliver the correct result for suitable "a" and "b", and trap for other values, you now have an operation that accepts any "a" and "b", and has a postcondition that includes traps. You have changed the function, and changed its specification, pre-conditions and post-conditions. > >> It means it is no longer true that the result of an addition operation >> is the sum of the operands. > > Oposite of that: no traps means that regardless of precondition > the result of an addition operation is the sum of the operands. > Your change means that either the result is no traps and a correct sum, /or/ it is a trap and no valid sum (what you get returned as the "sum" will depend on how you define all this). I think, perhaps, what you mean here is that if you do something like "x = a + b;", and the execution makes it through the addition and does the assignment, then "x" is guaranteed to be equal to the sum of "a" and "b". That is fair enough - without such guarantees, traps, exceptions, etc., would be a completely useless concept. >> Addition is no longer a "pure" function - >> now it has side-effects that are completely unpredictable at the site of >> use. Programmers can no longer rely on the timing of the operation, >> stack usage, interaction with other code, or even that the operation >> ever finishes. > > The difference is that without traps programmers do not know if > arithmetic operations give correct result. They do know - if the code is written correctly. They know the result is correct because they know they have fulfilled the pre-conditions. It is the caller code that has the responsibility to make sure the pre-conditions hold. If the programmer does not know if the pre-conditions will hold before the call, then they don't know what their code will do. And that is not a good situation to be in - the possibility of some unknown jump to somewhere else in the code does not make it better. Note that all of this is different from run-time failures that might occur in the normal course of the program, outside of the knowledge or control of the calling code. C++ exceptions, or C error return codes, are fine for things like a "read file" function in the case when the file does not exist. That is not the result of a bug in the code. (Well, it might be, but it doesn't have to be.) It is an expected situation that can be handled. Traps on UB are unexpected situations resulting from bugs in code. They can be helpful for fault-finding, and may have some uses in damage limitation. > With traps they do > not know if program will successfully finish, but if it > finishes they know that arithmetic gave correct results. > This is achievable in a controlled manner, without traps. >> If your code is correct, and overflow never happens, then this is all a >> big disadvantage in terms of understanding and analysing the code. And >> it does not in any way reduce the effort needed to be sure that your >> inputs are appropriate for getting the desired results of the operation. > > One needs to use correct formulas, there is no way around that. > Without traps programmer must analyse ranges of all intermetiate > expressions. That is tedious and error prone. Then do a better job of it - or find ways that are not as tedious. The main reasons for getting integer overflow are : 1. Using unsanitised input. 2. Using types that are too small. 3. Not having a clear idea of what kinds of values you are dealing with, and what you are doing with them. The way to avoid 1 is obvious. The way to avoid 2 is obvious (except in the very rare situations where 64-bit integers are not big enough). The way to avoid 3 is obvious. (Sometimes the details of implementing these fixes are not minor, but the principle is clear.) > People work > around that by activating traps during testing, but it is > quite hard to find worst case values, so errors may be > easily missed during testing. Having traps active during > production runs means that you may discover problem. You > apparently think that ignoring possible problems at > runtime is good thing. No, ignoring problems is never a good thing. Writing code that doesn't run the risk of problems is a good thing. And I can agree that sometimes leaving traps enabled in released code can be helpful - there are situations where you can't practically remove the risk of overflows, and it is better to crash out reliably than risk running on with faulty data. It is, however, also the case that sometimes traps will cause far more problems than incorrect data would. (Noting that UB does not guarantee "incorrect data" - it can do anything. Wrapping semantics, or unspecified value semantics, would do that.) > For simple programs you may analyze > it well enough to be sure that nothing bad happens at > runtime, but in general computing we use a lot of "interesting" > programs which are too complex to analyse. We hope that > they will run OK, but have no proof. Sometimes hope is > based on statistical tests and on low probability input > program may fail. Traps are useful to make sure that > wrong results will not propagate further. > This is why you break your code down into manageable and understandable parts - functions, classes (for some languages), modules / translation units, files, directories, libraries. Yes, there can be interactions that can be very difficult to test well - testing is not easy. Code over a certain size is likely to contain bugs - programmers are rarely infallible, and even when they are ( :-) ), the customer specifying the program is not. But we are talking here about a specific class of bugs - UB that can be detected by trap options in code generation or cpu hardware, which basically means integer overflows, divide by 0, dereferencing null pointers, and shift by inappropriate amounts. Those bugs are avoidable - I really do not see them as a concern. Trapping won't help all the other bugs - buffer overflows, unterminated strings, index out of range, misunderstanding the specifications, mixing up parameter order in function calls, data races, logical errors, memory resource ownership mixups, and everything else. So your traps on arithmetic overflow is crippling the efficiency of calculations (and efficiency of calculations is a big reason for picking C in the first place) to give unexpected crashes when easily preventable mistakes occur - while doing nothing to aid the big risks. >> Trapping like this can certainly be useful for debugging. But as a >> general feature it gives a false sense of security, complicates >> mathematical analysis, introduces massive additional possible code path >> choices which are either real or almost certainly untested in practice, >> or not real (because the compiler can see they are not taken) and >> untestable. > > You get extra code paths only if you attempt to handle traps. Unhandled traps are also a code path. > Trapping of overflows gives you assurance that in computation that > you did and which finished with no traps there were no errors of > certain kind (that is wrong results due to overflow). That is > really not different than insistence on static types. They are not remotely the same - the distinction between compile-time and runtime is critical. > Neither > assures you of no bugs, but each tells you that some bugs > did not happen. Of course, trapping at runtime is less > satisfactory than compile time checking, but tight a priori > bounds on ranges are notoriusly hard to obtain, so trapping > is the best we can have for high performance software with > current state of art. > >> That is not qualitatively worse than "who knows what will >> happen" UB, but it is not significantly better. >> >> >>> <snip> >>> >>>> The correct way to handle the situation is to avoid it - be sure that >>>> you are not dividing by zero in the first place. Identify and handle >>>> the problem where it occurs - when this zero is created, or the >>>> circumstances leading to that point - rather than trying to do a >>>> post-mortem after the failed division. And if you are doing that, then >>>> what benefit is there in having trapping for division by zero? It >>>> becomes just a waste of effort. >>> >>> What is value of certification required for some software? If >>> programmer did good job then program will work correctly. >> >> Yes. >> >>> Trap give assurance that programmer indeed correctly handled >>> tricky problem. >> >> No, it certainly does not. And one of the reasons to dislike traps is >> that it makes people think like that. A trap can only happen if the >> programmer did /not/ handle the problem correctly. > > Yes. > >> And I expect that if >> the programmer is able to write an appropriate specific trap handler for >> the failing expression (rather than a program-global "crash with error >> message" handler), then he/she would be able to avoid the problem in the >> first place. > > Rather non-specific trap handler could work as "redo the computation > in arbitrary precision". If problem (like division by zero) persists, > then there is logic bug, otherwise it means that precision was > inadequate and problem is resolved. > If you are talking here about using traps as a testing and debugging aid, helping the developer spot problems and improve their code, then I agree - that's a good thing. If you are talking about some kind of automatic handling, then that is totally out of scope for a language like C. It would be much more appropriate to use a higher level managed language and higher level arithmetic (like support for arbitrary precision integers) in the first place. > Howver, you should think about such traps similarly to parity error > which can be signaled by some hardware. There is low but nonzero > probablity that such error can occur. Parity check gives you > reasonable chance to detect it. That's not an unreasonable comparison. Parity checks used to be popular - they are almost non-existent in communication protocols now. You either have something that you know works correctly, or you use much better methods - multiple ECC bits, CRCs, FEC, or whatever, according to the balance of cost, error rates, consequences of data loss, etc. > Handling is at least as problematic > as with overflow. Absence of traps gives you less info: no > overflow traps mean no overflow, no parity traps means that > parity was correct, but intent of parity check it to discover bit > error and they are possible even with correct parity. So, do you > think that parity check inside MCU-s are useless? Yes, for the most part. A parity check is almost always either unnecessary, or not nearly enough. > >> Sometimes, of course, you are trying to write code that has some input >> which is supposed to be correct, but you are not sure - and you can't >> change the calling code. How you handle that situation will depend on >> the program and the situation. But I don't see trapping as "correct >> handling" unless the whole program is written with the expectation of >> traps for error handling. You might, however, end up deciding that >> trapping is the least bad option. >> >> >>> And once you know that computation works >>> according to math rules other forms of verification are easier. >>> >>> You also seem to have bias to real time control: if you need >>> value just at given moment, then it is hard to do something >>> reasonable. But at least in some control areas there is >>> notion of "safe state", for example working heavy machine >>> is dangerous, stopped one usually is considerd safe. If >>> there is safe state, then anything not expected by program >>> should trigger transition to safe state. >> >> I think if you are /not/ concerned with high efficiency in the code, > > Well, if efficiency does not matter traps can be implemented as > a software layer above the language. Or one can use arbitrary > precision arithmetic. Traps matter when efficiency matters, > so they should be implemented in place giving best efficiency, > at best in CPU and if that is not possible then in optimizing > compiler. > >> then you should be seriously questioning the choice of C as the language >> in the first place. And even if you use C, there are often things you >> can do to avoid having problems in the first place. The obvious one for >> integer overflow is to make more use of bigger types. > > Which may be best choice if efficiency is not important. But > some calculations require surprisingly large accuracy to avoid > overflow. Worse, in vast majority of cases lower accuracy > may be adequate, so there is pressure to use "sufficient" > accuracy overlooking special cases. > >>> In general computation, if you need correct value and have some >>> time there are options which may involve re-doing computation at >>> higher precistion, which may get rid of occasional overflows >>> and divisions by zero due to overflow. Division by zero may >>> be due to bad input data, traps allow indentification of >>> such data (doing it in other way may be computationaly quite >>> expensive). >>> >> >
[toc] | [prev] | [next] | [standalone]
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-06-24 17:45 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <111gu2i$305a3$3@dont-email.me> |
| In reply to | #400080 |
On 2026-06-16 10:10, David Brown wrote: > On 15/06/2026 19:57, Waldek Hebisch wrote: >> [...] > > No, ignoring problems is never a good thing. Writing code that doesn't > run the risk of problems is a good thing. Sure. > > And I can agree that sometimes leaving traps enabled in released code > can be helpful - there are situations where you can't practically remove > the risk of overflows, and it is better to crash out reliably than risk > running on with faulty data. It is, however, also the case that > sometimes traps will cause far more problems than incorrect data would. > (Noting that UB does not guarantee "incorrect data" - it can do > anything. Wrapping semantics, or unspecified value semantics, would do > that.) Hmm.. - not sure what you mean (and imply with) "crash out reliably". Having been engaged in server systems software development a crash had never been an accepted option. And that's certainly also true with life-critical applications and costly operations (upthread you had mentioned Ariane 5). You should always avoid crashes and catch exceptions. The point is what you can then do with that information, and that depends on the actual application case; report it, retry it, retry with alternative methods or adapted conditions, emulate the result, estimate it, ask supervisor process, switch devices, etc. I'm well aware that wrong data may also be bad, be it from a wrong algorithms, a technical overflow situation, unreliable data sources, or an unreliable processing (not-excluding effects of UB). I'm really not sure whether to consider "not handling an exception" better or worse than "not handling data errors"; usually you don't want either. So both should prevented (if possible) or acted upon (if getting a notice about it). Janis > [...]
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2026-06-24 12:27 -0700 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <111hb3j$38qg5$1@dont-email.me> |
| In reply to | #400231 |
On 6/24/2026 8:45 AM, Janis Papanagnou wrote: > On 2026-06-16 10:10, David Brown wrote: >> On 15/06/2026 19:57, Waldek Hebisch wrote: >>> [...] >> >> No, ignoring problems is never a good thing. Writing code that >> doesn't run the risk of problems is a good thing. > > Sure. > >> >> And I can agree that sometimes leaving traps enabled in released code >> can be helpful - there are situations where you can't practically >> remove the risk of overflows, and it is better to crash out reliably >> than risk running on with faulty data. It is, however, also the case >> that sometimes traps will cause far more problems than incorrect data >> would. (Noting that UB does not guarantee "incorrect data" - it can do >> anything. Wrapping semantics, or unspecified value semantics, would >> do that.) > > Hmm.. - not sure what you mean (and imply with) "crash out reliably". > > Having been engaged in server systems software development a crash > had never been an accepted option. And that's certainly also true > with life-critical applications and costly operations (upthread you > had mentioned Ariane 5). You should always avoid crashes and catch > exceptions. Right. Also, fwiw, I had a calibration system for my server framework that would artificially crash a system while keep logs. On reboot, it read the results and self calibrated itself. The point is what you can then do with that information, > and that depends on the actual application case; report it, retry it, > retry with alternative methods or adapted conditions, emulate the > result, estimate it, ask supervisor process, switch devices, etc. > > I'm well aware that wrong data may also be bad, be it from a wrong > algorithms, a technical overflow situation, unreliable data sources, > or an unreliable processing (not-excluding effects of UB). > > I'm really not sure whether to consider "not handling an exception" > better or worse than "not handling data errors"; usually you don't > want either. So both should prevented (if possible) or acted upon > (if getting a notice about it). > > Janis > >> [...] >
[toc] | [prev] | [next] | [standalone]
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-06-24 16:58 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <111gras$305a3$2@dont-email.me> |
| In reply to | #400061 |
I'm entering this sub-thread late and yet I haven't finished reading all posts. - While I lately noticed some convergence of opinions and facts this post appears to me to mostly fall back again; but I won't re-open the discussion. I just want to comment on a single exposition. On 2026-06-15 10:09, David Brown wrote: > On 15/06/2026 00:55, Keith Thompson wrote: >> [...] > [...] > > Throwing some kind of exception or trap can definitely be helpful at > times. And I agree that it would make it obvious that there has been a > problem detected. But throwing exceptions or traps can cause more > problems (the Ariane 5 failure was caused by the exception handler, not > the overflow fault). That does not mean it is better to ignore > overflows - it means there is no appropriate action that is suitable in > every situation. I am far from convinced that there is even a > reasonable choice of default action that could be usefully made. (I don't expect the complete investigation report on the Ariane 5 incident being represented or explained, but picking a few facts is not only an oversimplification here, it lead to a misrepresentation of the case and inappropriate reasoning and conclusions.) Throwing an exception in a system that should have a well-defined and safe behavior is of course stupid. Exceptions are there to catch them and handle them with appropriate actions to mitigate or fix any issue. Not UB, but well defined software and well defined system behavior is the key! That should be not only in aviation and life-critical systems but (ideally) also in "ordinary" software development with used tools. The problem with the Ariane 5 was a sequence and combination of events. But the _primary cause_ had not been the [technical] interrupt. It was the fact that the *requirements* (the flight trajectories) changed from Ariane 4 to Ariane 5 and that they didn't adjust the system accordingly but just re-used formerly designed system components unchanged. (This actually reminds (or resembles?) more the case that Dan narrated; of using old software systems with new tools, that "unexpectedly" fails in a new compiler-environment, because of a component in another place that was just "invisible" at the place where the problem got triggered.) In retrospect it is clear that all the software components with their contracts should have been double-checked against the (new) Ariane 5 requirements - that hadn't been done and that was the problem source! (There's a reason why they use Ada and not "C" in such areas; the rocket might otherwise have exploded on the launching-ramp already. ;-) Janis > [...]
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-15 19:26 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <110pjko$o78$1@reader1.panix.com> |
| In reply to | #400053 |
Prefatory: I think we're largely in agreement; I'll just add a few notes, but snip most of the rest. In article <110n1db$3sbck$1@dont-email.me>, David Brown <david.brown@hesbynett.no> wrote: >[snip] >Maybe there is scope for compilers to have better options for handling >old code, other than the usual "Use -O0 to avoid optimising on UB" >solution. You could come a long way with a "treat all variables as >volatile" flag, for example. The problem is, the language doesn't make any guarantees here, and the compilers get to decide. If you're lucky, the compiler gives you some control via flags or pragmas or something, but if you're not lucky, it doesn't and the guarantees you can rely on are just too weak. >[snip] >That can certainly happen. But that's just bugs in the code. I don't >see why UB should be considered as something special here. Because unlike many bugs, which are clearly bugs, UB is just the absence of defined behavior. So the output of a program executes can change in subtle ways with no changes to the code, only changes to the compiler or how it is invoked. >People >making changes to existing code sometimes misunderstand things, or >accidentally break something that worked before. That's life as a >programmer, and there are techniques to reduce the risk - code reviews, >linters, testing regimes, etc. Nothing gives 100% guarantees, and >everything has to weigh risks, consequences, costs and resources. UB is >not special here. Yes. My point with this line is that UB doesn't show up because programmers are just careless, and "just write code more carefully" doesn't scale any better than, "have you tried just writing code without bugs?" >UB means precisely that I can choose trapping, or IB, or optimising on >the assumption it does not happen. If signed integer overflow were >defined as wrapping, then compilers could not put in traps to catch the >errors because as far as the language is concerned, they are not errors. If "you" means the compiler, then sure. If "you" means the programmer, then you are lucky if you get to choose that, but it is not guaranteed that you will have that kind of flexibility available. > If they are defined as causing traps, then that's the semantics - >compilers could not optimise code assuming overflow does not happen, >unless it can prove there is no overflow. > >And making it defined behaviour gives programmers the mistaken idea that >they don't need to avoid overflow because there is no UB. > >Making this UB is an admission of the blindingly obvious - there is no >correct answer when signed integer overflow occurs. It tells >programmers that it is a mistake to let your arithmetic overflow, and it >allows tools to help programmers avoid these mistakes, and it allows >compilers to give programmers the most efficient results from known good >code rather than adding unnecessary run-time checks that are never >triggered. But it doesn't say that. It says, "no guarantees; whatever happens happens." This is the thing: the correct answer is whatever the language defines it to be. The language could say, "this is an error" or it could say, "we do whatever the hardware does." But making it UB isn't a statement of anything. UB is a refusal to make a statement. >[snip] >(I think you missed a bit of your answer here?) (I did, but i was just going to say something about memcpy; it wasn't that interesting. :-/) >>>> [snip] >>>> I realized that we were not speaking the same language _at all_. >>>> He and I both wanted a language where we could write programs >>>> that yield efficient object code. He saw UB as essential for >>>> that; but what I want is a language with well-defined semantics >>>> that can be aggressively optimized. >>> >>> I too want a language with well-defined semantics that can be >>> aggressively optimised. But I do not see UB as a hinder to that. >> >> UB is literally the opposite of well-defined. > >I want good definitions of things that should be defined. Things that >cannot have good definitions, are fine left undefined. A language >standard should not be trying to define the behaviour of /everything/. I accept that there will be some number of things that one cannot reasonably define when creating a programming language. But that set should be small; >>> I am happy knowing that I cannot divide by 0, >> >> Yup. That should be a trap. > >For some programs, yes. For others, no. No. I don't accept that division by zero is ever acceptable in a real program. What purpose would be served by _not_ trapping? Most hardware will do it anyway. >>> or find the square root of a negative number (in the real >>> domain). >> >> Yup. That should be a trap. > >For some programs, yes. For others, no. Same as above. If you want a NaN to be a possbility, you should use an operation that lets you get that, `unchecked_sqrt()` or something. >>> I am happy knowing that I cannot add two ints if their sum >>> overflows the range of their type, >> >> Yup. That should be a trap (if you want wrapping semantics, you >> should request it explicitly). > >I agree that wrapping semantics should be something you have to ask for. > (As an aside, I think it is a mistake for languages to have types that >have wrapping semantics - it's the operations that should wrap, not the >types. Zig gets it right by distinguishing between "x + y" and "x +% y".) Yes. Rust has this as well, in `.wrapping_add()` et al. >I don't want to pay the price for checks, traps, and limited >re-arrangements and optimisations when I know my expressions don't >overflow. But I am also happy to be able to get a trap when I ask for it. Then the language should give you the ability to explicitly ask for the unchecked versions of those operations. >But I think it is equally bad to give things a definition simply to be >able to say there is no UB. I'm not suggesting that one should do that. What I'm saying is that it is possible to conceive of a language that lets you write robust, complex programs with strong guarantees about the behavior of code, without UB. That doesn't mean that the language is devoid of all notions of undefined behavior, but rather that unless you ask for it, using UB is an error. >It is, IMHO, entirely /wrong/ of a language >to define integer overflow as wrapping simply so that it is not UB. I >do not see a guaranteed incorrect result that likely has catastrophic >consequences in a program as being better than UB. We've discussed this before, and I understand your perspective on it, but I feel it necessary to reiterate that I do not share that perspective. Defining arithmetic to be modular is perfectly acceptable. It is not "wrong". Defining arithmetic on explicitly sized types to use 2's complement semantics similarly. C defined arithmetic overflow for signed types to be UB because when it was standardized, machines existed that had different behavior and representations for signed types. Why didn't they make it IB? I don't know. The world is different now. >(I believe Rust >defines integer overflow as trapping in "debug" mode and wrapping in >"release" mode, which I think is a horrendous idea.) I agree that's kind of a wart. It's basically what you get with UB in C. In my opinion, the right call is providing an `unchecked_add` and forcing the caller to wrap that in an `unsafe` block, while normal `+` is always checked unless the compiler can deduce that overflow cannot happen. https://doc.rust-lang.org/std/primitive.u32.html#method.unchecked_add >> So I was the one who said "well-defined semantics" and I had a >> specific meaning in mind. Your definition is incomplete with >> respect to that meaning: in addition to what you said, invalid >> inputs should be rejected, either as a compile time error, or by >> generating an exception or panic at runtime. If you want to >> live dangerously and turn the runtime checks off for performance >> reasons, then you get 2's complement behavior for integers or >> whatever the machine does for the others. > >I am all in favour of compile-time checks and rejecting code with errors >(not just UB) as soon as possible. The "perfect" language is one where >you really can follow the old Ada saying - if you can make it compile, >it's ready to ship. > >I don't live dangerously by not having run-time checks on integer >overflows. I make sure my code does not have them, so checks are >unnecessary. For some of my code, if it "panicked" somewhere in >calculations, that would be a disaster - when you have code controlling >power electronics, a sudden stop can mean short-circuits and components >releasing their magic grey smoke. This doesn't follow. If you have validated that the code cannot overflow, and you are confident in that, then the code won't panic due to overflow. So arguing against the validation seems superfluous. And of course if the compiler can validate that your code is free of overflow (perhaps by examining your checks) then it needn't insert the checks, so there is no runtime overhead. >Thinking that run-time checks will save you from UB is wishful thinking. > How are you going to have run-time checks that a pointer parameter >points to a valid object of the right type? In strongly-typed languages with non-nullable references and lifetimes as a first-class property of an object, the compiler does that for you, statically, at compile-time. >You can check for a >null-pointer, but that's about it. Some things that are potential UB in >C are inherent in the type of language - checking for such problems (at >compile-time or run-time) needs a language that has a different way of >handling objects and pointers so that you cannot have arbitrary pointers >to arbitrary objects. > >C is not a language suitable for such run-time or compile-time checks - I agree. >it is a language for getting the highest efficiency because the >programmer takes responsibility for getting things right. Paradoxically, this is not true. Consider pointers: because they can be invalid, they have to be checked before dereference. Contrast to non-nullable references in e.g. Rust; since their mere existence implies that they refer to a valid object, they do not need to be checked for nullity, misalignment, etc. Thus, the better-defined language with stronger guarantees can afford opportunities for optimization that don't exist in the lower-level language riddled with UB. >You are >correct that large programs normally have bugs (of which UB is just one >class) - the risk of bugs goes up with the size of the code base. The >corollary is that C is not a language suitable for large programs. Sadly, I now agree. >Rust, I think, reduces the risk of some kinds of bugs. So does C++, >when used carefully. Most code, however, is best written in languages >where these issues cannot occur - or at least where checks can be done >without a measurable impact. For example, if you use Python, you never >have integer overflow, and you never have invalid pointers. If you use Rust, and restrict yourself as far as practical to the safe subset, you never have invalid pointers, either. Nor do you have uninitialized variables, or double-frees, or data races. Entire categories of problems --- and their expensive runtime checks --- are simply eliminated. >> [snip] >> Consider one of the examples you gave: signed integer overflow. >> The standard doesn't say that you _can't_ add two numbers >> together if you overflow, it just says that if you do, the >> language imposes no requirements on the resulting behavior. It >> may trap, it may elide the addition entirely, or it may do it >> and let the result be whatever the underlying machine does. >> >> That is, the _language_ does not say that it's a bug; it says >> that it's not going to say anything about it at all. > >I'd be happy for the C standard to say that signed integer overflow is a >bug, or that code is not allowed to overflow its integer arithmetic. I >would not be happy if it said compilers must trap on the bug or handle >it in some specific way - what happens when a bug is reached is still >UB. And if the wording of the standard were changed to call it a "bug" >rather than "UB", it would make absolutely zero difference to the way I >write my code. This is an example of two people who are not sharing a vocabulary around UB. I have no real commentary on that; I just think it is interesting. >[snip] >In my field, people usually put a lot of effort into writing code simply >and clearly. You avoid mistakes not by being "clever", but by being >meticulous and careful. I don't think successful C programming requires >greater intellect, knowledge or experience compared to other programming >languages - but it /does/ require an appropriate attitude. You are >working with sharp knives - pay attention to what you are doing, and >you'll be fine. 50 years of experience shows us that that simply isn't true. "Pay attention" and "be careful" just don't work. >> My experience is that most programmers are highly intelligent, >> capable people. They are not wrong to want behavior they can >> rely on, particularly when things are not obvious, as they >> often are not. They also want a language that requires a less >> lawyerly read of to understand its semantics; that could go the >> way of formality (my preferred approach) or just clearer >> exposition. Either would be preferable to the current state. > >I was avoiding signed integer overflow long before I had read any C >standards or even knew about the term "UB". Programming in C does not >need a lawyer knowledge of the language. It is just like programming in >any other programming language - use features that you know are correct, >and if you want to do something and don't know how to do so correctly, >look it up. Right. But the issue is that the source of truth, the standard, is ambiguous in places and opaque in others. Sussing out the true semantics of a thing can be cross-referencing half a dozen different places, and this newsgroup sees cases where people who are clearly intelligent, and who have an aptitude for programming in C, can disagree on the specific meaning of things in the standard. Frankly, I think much of that is a waste of time. Let's have better definitions, and more rigorous exposition. >> [snip] >> Exactly. The footguns hiding in C code that has worked >> perfectly for decades, dating back to before the standards >> existed, are legion. Caveat emptor. >> >> _Or_ the code may have been written with careful regard for the >> standard, but something _else_ may have been changed that now >> leads to exposure to UB. For example, perhaps code was written >> that multiples two numbers, `a*b`; a known to be `unsigned int` >> when written, but `b` is a signed int. But maybe that is hidden >> behind a typedef; some time in the future, the typedef is >> changed so that `a` is now `unsigned short`; perhaps someone >> realized that the domain values never exceed 16 bits and by >> changing the definition some critical structure now fits in a >> single cache line. But also now the type promotion rules kick >> so that `a*b` happens with the factors as `signed int` and in >> there exist values of `a` and `b` where `a*b` overflows: UB. >> >> The code had no UB; the change was elsewhere; no one saw this >> because the tests all passed and everything looked ok; then >> someone upgrades the compiler and now things break. >> >> Who's fault is that? > >There's no simple answer here. > >But one thing is clear to me - "UB" is irrelevant here (and in many of >your points). It would not matter if everything had fully defined >behaviour. The point is that something is changed in one part of the >code that has unexpected consequences in another part of the code. Who >cares if there is UB or not? The issue is that the code does not work >as intended or expected. UB can provide situations where you have >unexpected bugs - but so can all sorts of other things. UB is the essential characteristic here. With a better defined language, these issues are either compile-time failures, or they become immediately apparent during testing. In the face of C-style UB, however, they become spooky action at a distance; the realized effect of the change may not manifest as a bug for many years. >> And no, this is not contrived; this is exactly the sort of thing >> that happens on large, long-lived projects. >> >>>> As said earlier, C is what it is. I suspect that it will >>>> continue to make incremental improvements, but we're basically >>>> stuck with what we have. >>> >>> Agreed. >> >> ...but be careful blaming the programmer. > >Or the language, or the tools. I push back on both of these. There's an old saw that goes, "a good craftsman never blames his tools." (I dislike it, but that's how it usually goes.) But there's an unstated corollary: a good craftsman also maintains and carefully selects the tools for the job at hand. You don't smooth a rough-cut board with a screwdriver, nor do you turn a bolt with a hammer. And you don't use a chainsaw without a guard. - Dan C.
[toc] | [prev] | [next] | [standalone]
Page 8 of 23 — ← Prev page 1 … 6 7 [8] 9 10 … 23 Next page →
Back to top | Article view | comp.lang.c
csiph-web