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 250 — 20 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 Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-05 10:41 +0200
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 "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 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 "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-04 15:25 -0700
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 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 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 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 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: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 03:58 -0700
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 5 of 13 — ← Prev page 1 … 3 4 [5] 6 7 … 13 Next page →
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-02 16:28 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <10vn0bk$ghg$1@reader1.panix.com> |
| In reply to | #399615 |
In article <86ik81cfk5.fsf_-_@linuxsc.com>,
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>
>> On 2026-06-01 00:54, Keith Thompson wrote:
>>
>>>> [...]
>>>
>>> Yes, a compiler can reduce (a + b) * 0 to just 0. But it's not
>>> required to do so, and (INT_MAX + 1) * 0 still has undefined
>>> behavior. Undefined behavior is determined by the rules of the
>>> abstract machine *without* any adjustments permitted by the as-if
>>> rule.
>>
>> This is something I really don't get in the actual C-logic...
>>
>> Using constants that can be determined at compile time is UB here,
>> despite the '* 0' mathematically indicating an IMO clear semantics,
>> but using variables is only UB possibly at runtime? [...]
>
>There's an important distinction to make here. Consider this
>program:
>
> #include <limits.h>
>
> int
> foo(){
> int zero = (INT_MAX+1)*0;
> return zero;
> }
>
> int
> main(){
> return 0;
> }
>
>This program does not transgress the bounds of undefined behavior.
Given that `foo` has external linkage, I find this hard to
believe, and `clang -fsanitize=undefined` agrees with me,
both emitting a diagnostic about the overflow and generating
code in `foo` to call into the sanitizer machinery.
Perhaps you mean that this is irrelevant because `foo` is not
invoked, but I see no reason why that need be the case in e.g.
a freestanding environment. In a hosted environment, I don't
think anything explicitly prevents `foo` from being called after
`main` returns (though I can't imagine that would happen in real
life; it would be weird if it did).
But I'm not sure what _you_ mean by "transgress the bounds of
undefined behavior" here.
>Even more than that, the program is strictly conforming, and must be
>accepted by a conforming implementation.
See above.
>Now let's change the program slightly:
>
> #include <limits.h>
>
> int
> foo(){
> static int zero = (INT_MAX+1)*0;
> return zero;
> }
>
> int
> main(){
> return 0;
> }
>
>This program does transgress the bounds of undefined behavior. The
>reason for the difference is that in the first program the semantics
>of foo() is to evaluate the expression to be stored in 'zero' only
>at runtime, whereas in the second program the semantics of foo() is
>to evaluate the expression to be stored in 'zero' before program
>startup (informally, "at compile time"). What matters is not
>whether the offending expression /might/ be evaluated "at compile
>time", but whether the offending expression /must/ be evaluated "at
>compile time". Only in the second case is undefined behavior
>inevitable (and thus it does not occur in the first program).
>
>Fine point: strictly speaking, I believe the C standard allows even
>the second program to complete translation phase 8 successfully, and
>for any offending behavior to occur only when we actually try to run
>the program. To say that another way, there is no requirement that
>possible nasal demons be made manifest at any point before an actual
>attempted execution. On the other hand, because that possibility is
>there lurking in the background, there is no requirement that the
>program be accepted, and could be rejected by a conforming compiler.
Indeed. Further, I believe that the same is true for the first
program, as well.
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2026-06-04 03:37 -0700 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <865x3yd21n.fsf@linuxsc.com> |
| In reply to | #399636 |
cross@spitfire.i.gajendra.net (Dan Cross) writes:
> In article <86ik81cfk5.fsf_-_@linuxsc.com>,
> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>>
>>> On 2026-06-01 00:54, Keith Thompson wrote:
>>>
>>>>> [...]
>>>>
>>>> Yes, a compiler can reduce (a + b) * 0 to just 0. But it's not
>>>> required to do so, and (INT_MAX + 1) * 0 still has undefined
>>>> behavior. Undefined behavior is determined by the rules of the
>>>> abstract machine *without* any adjustments permitted by the as-if
>>>> rule.
>>>
>>> This is something I really don't get in the actual C-logic...
>>>
>>> Using constants that can be determined at compile time is UB here,
>>> despite the '* 0' mathematically indicating an IMO clear semantics,
>>> but using variables is only UB possibly at runtime? [...]
>>
>> There's an important distinction to make here. Consider this
>> program:
>>
>> #include <limits.h>
>>
>> int
>> foo(){
>> int zero = (INT_MAX+1)*0;
>> return zero;
>> }
>>
>> int
>> main(){
>> return 0;
>> }
>>
>> This program does not transgress the bounds of undefined behavior.
To clarify, the comments in my posting were meant to be read as
saying the given text is the entire program, and that it is strictly
conforming with respect to conforming hosted implementations.
(Incidentally, given the rules for freestanding implementations, I'm
not sure that it is even possible for any program to be strictly
conforming with respect to conforming freestanding implementations.
In any case my statements were meant only in the context of hosted
implementations.)
> Given that `foo` has external linkage, I find this hard to
> believe, and `clang -fsanitize=undefined` agrees with me,
> both emitting a diagnostic about the overflow and generating
> code in `foo` to call into the sanitizer machinery.
A conforming implementation is free to emit a diagnostic whenever it
chooses, for any reason at all, regardless of whether the program
source is legal C or not. (I feel obliged to point out that, if a
preprocessing #error directive is encountered, then there may be an
exception to that statement; however, there is no such #error in
the program shown above.)
> Perhaps you mean that this is irrelevant because `foo` is not
> invoked, but I see no reason why that need be the case in e.g.
> a freestanding environment.
I explained the context of my previous statements above. Sorry for
not saying that in the original message.
> In a hosted environment, I don't
> think anything explicitly prevents `foo` from being called after
> `main` returns (though I can't imagine that would happen in real
> life; it would be weird if it did).
The semantics described in the ISO C standard don't admit that
possibility. Whether foo() has external linkage or internal
linkage doesn't change that. Only those actions initiated by
statements in main() are ever elaborated.
> But I'm not sure what _you_ mean by "transgress the bounds of
> undefined behavior" here.
It's a grammatical fine point. I think for present purposes it's
okay to gloss over the distinction, and say this statement may be
read as saying "the program does not have undefined behavior".
>> Even more than that, the program is strictly conforming, and must be
>> accepted by a conforming implementation.
>
> See above.
>
>> Now let's change the program slightly:
>>
>> #include <limits.h>
>>
>> int
>> foo(){
>> static int zero = (INT_MAX+1)*0;
>> return zero;
>> }
>>
>> int
>> main(){
>> return 0;
>> }
>>
>> This program does transgress the bounds of undefined behavior. The
>> reason for the difference is that in the first program the semantics
>> of foo() is to evaluate the expression to be stored in 'zero' only
>> at runtime, whereas in the second program the semantics of foo() is
>> to evaluate the expression to be stored in 'zero' before program
>> startup (informally, "at compile time"). What matters is not
>> whether the offending expression /might/ be evaluated "at compile
>> time", but whether the offending expression /must/ be evaluated "at
>> compile time". Only in the second case is undefined behavior
>> inevitable (and thus it does not occur in the first program).
>>
>> Fine point: strictly speaking, I believe the C standard allows even
>> the second program to complete translation phase 8 successfully, and
>> for any offending behavior to occur only when we actually try to run
>> the program. To say that another way, there is no requirement that
>> possible nasal demons be made manifest at any point before an actual
>> attempted execution. On the other hand, because that possibility is
>> there lurking in the background, there is no requirement that the
>> program be accepted, and could be rejected by a conforming compiler.
>
> Indeed. Further, I believe that the same is true for the first
> program, as well.
It isn't. In the first program the offending expression is never
evaluated, because foo() is never called.
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-04 16:31 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <10vs997$rp5$1@reader1.panix.com> |
| In reply to | #399674 |
In article <865x3yd21n.fsf@linuxsc.com>,
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>> In article <86ik81cfk5.fsf_-_@linuxsc.com>,
>> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>>>> On 2026-06-01 00:54, Keith Thompson wrote:
>>>>>> [...]
>>>>>
>>>>> Yes, a compiler can reduce (a + b) * 0 to just 0. But it's not
>>>>> required to do so, and (INT_MAX + 1) * 0 still has undefined
>>>>> behavior. Undefined behavior is determined by the rules of the
>>>>> abstract machine *without* any adjustments permitted by the as-if
>>>>> rule.
>>>>
>>>> This is something I really don't get in the actual C-logic...
>>>>
>>>> Using constants that can be determined at compile time is UB here,
>>>> despite the '* 0' mathematically indicating an IMO clear semantics,
>>>> but using variables is only UB possibly at runtime? [...]
>>>
>>> There's an important distinction to make here. Consider this
>>> program:
>>>
>>> #include <limits.h>
>>>
>>> int
>>> foo(){
>>> int zero = (INT_MAX+1)*0;
>>> return zero;
>>> }
>>>
>>> int
>>> main(){
>>> return 0;
>>> }
>>>
>>> This program does not transgress the bounds of undefined behavior.
>
>To clarify, the comments in my posting were meant to be read as
>saying the given text is the entire program, and that it is strictly
>conforming with respect to conforming hosted implementations.
>(Incidentally, given the rules for freestanding implementations, I'm
>not sure that it is even possible for any program to be strictly
>conforming with respect to conforming freestanding implementations.
>In any case my statements were meant only in the context of hosted
>implementations.)
Ok.
>> [snip]
>> Perhaps you mean that this is irrelevant because `foo` is not
>> invoked, but I see no reason why that need be the case in e.g.
>> a freestanding environment.
>
>I explained the context of my previous statements above. Sorry for
>not saying that in the original message.
>
>> In a hosted environment, I don't
>> think anything explicitly prevents `foo` from being called after
>> `main` returns (though I can't imagine that would happen in real
>> life; it would be weird if it did).
>
>The semantics described in the ISO C standard don't admit that
>possibility.
Could you please point to where it says this, in the C standard?
I cannot find anything that says that arbitrary code cannot run
after `main()` returns, and I don't see how that could possibly
be true.
>Whether foo() has external linkage or internal
>linkage doesn't change that.
I disagree. There's no possible way for the implementation to
know whether a function with external linkage will be ultimately
invoked or not; consider a system that supports loadable shared
modules. Nothing prevents even this simple program from being
compiled as a shared module, dynamically loaded, the loading
program explicitly searching for and finding the symbol
corresponding to the `foo` function, and invoking it.
Hence, the compiler _must_ treat with UB as written, which is
why `ubsan` inserts trapping code in `foo`.
In your example, `foo` clearly exhibits UB; I think your
argument is whether that has a realized effect or not, since the
UB is not invoked. I'm saying that in general a compiler cannot
possibly know that when it compiles `foo`, and is free to assume
the worst.
>Only those actions initiated by
>statements in main() are ever elaborated.
This is not true: code can obviously run outside of the bounds
of `main`, for several reasons.
First, there is the issue of static initializers, which you had
mentioned earlier. Not at play here, but it does invalidate
your statement above, as these run "before" main is invoked.
Second, we know that code can run after because `atexit` can be
used to register handlers that will run after it terminates: as
section 5.1.2.3.4 of n3220 says, "a return from the initial call
to the main function is equivalent to calling the exit function
with the value returned by the main function as its argument",
which means that it will run `atexit` handlers. (But, as the
footnote warns, lifetimes of variables with automatic storage
duration have ended in this case in accordance with sec 6.2.4,
since `main` has terminated.)
Third, it is possible to invoke code that may conditionally be
executed, such as signal handlers, in response to external
events. Certainly, `signal(SIGINT, some_handler);` does not
immediately guarantee that `some_handler` is run, but it does
not prevent it from running, either.
Of course, for the second and third points, we must acknowledge
that one might quibble about what it means to say that a program
invokes "actions initiated by statements in main()".
Registering signal and exit handlers is (generally) going to be
something done in as the consequence of an "action initiated by
statements in main()". And subsequent invocation of (say)
`some_handler` in the example above in response to receipt of a
`SIGINT` signal is arguably a consequence of that.
>> But I'm not sure what _you_ mean by "transgress the bounds of
>> undefined behavior" here.
>
>It's a grammatical fine point. I think for present purposes it's
>okay to gloss over the distinction, and say this statement may be
>read as saying "the program does not have undefined behavior".
Except it does. `foo` is an example of what Regehr calls a
"Type 3" function in https://blog.regehr.org/archives/213.
Also you are discounting time-travel; code not not actually
invoke UB to suffer from it. The mere existence of it can be
enough.
https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633
Moreover, undefined behavior simply is; the definition from the
C standard does not say that time-traveling "post-modern"
compilers are free to assume and do anything if they observe UB
anywhere in a program.
Here, because `foo` has external linkage, the compiler cannot
know whether `foo` is invoked or not, and I see nothing
preventing it from assuming that the entire program is in error.
In particular, I don't think there is anything that prevents a
compiler from simply emitting `int main(void) { abort(); }`.
>>> Even more than that, the program is strictly conforming, and must be
>>> accepted by a conforming implementation.
>>
>> See above.
>>
>>> Now let's change the program slightly:
>>>
>>> #include <limits.h>
>>>
>>> int
>>> foo(){
>>> static int zero = (INT_MAX+1)*0;
>>> return zero;
>>> }
>>>
>>> int
>>> main(){
>>> return 0;
>>> }
>>>
>>> This program does transgress the bounds of undefined behavior. The
>>> reason for the difference is that in the first program the semantics
>>> of foo() is to evaluate the expression to be stored in 'zero' only
>>> at runtime, whereas in the second program the semantics of foo() is
>>> to evaluate the expression to be stored in 'zero' before program
>>> startup (informally, "at compile time"). What matters is not
>>> whether the offending expression /might/ be evaluated "at compile
>>> time", but whether the offending expression /must/ be evaluated "at
>>> compile time". Only in the second case is undefined behavior
>>> inevitable (and thus it does not occur in the first program).
>>>
>>> Fine point: strictly speaking, I believe the C standard allows even
>>> the second program to complete translation phase 8 successfully, and
>>> for any offending behavior to occur only when we actually try to run
>>> the program. To say that another way, there is no requirement that
>>> possible nasal demons be made manifest at any point before an actual
>>> attempted execution. On the other hand, because that possibility is
>>> there lurking in the background, there is no requirement that the
>>> program be accepted, and could be rejected by a conforming compiler.
>>
>> Indeed. Further, I believe that the same is true for the first
>> program, as well.
>
>It isn't. In the first program the offending expression is never
>evaluated, because foo() is never called.
See above.
Of course, I don't think any of this would _actually_ happen,
and if it did, one should take the compiler that does it and
toss it in the trash. But I don't think it's prohibited,
either; such is one of the consequences of an informal
specification like the C standard. Time-travel is especially
pernicious in post-modern compilers.
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-06-04 13:36 -0700 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <10vsnl7$lkmu$1@kst.eternal-september.org> |
| In reply to | #399693 |
cross@spitfire.i.gajendra.net (Dan Cross) writes:
> In article <865x3yd21n.fsf@linuxsc.com>,
> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>>> In article <86ik81cfk5.fsf_-_@linuxsc.com>,
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
[...]
>>>> There's an important distinction to make here. Consider this
>>>> program:
>>>>
>>>> #include <limits.h>
>>>>
>>>> int
>>>> foo(){
>>>> int zero = (INT_MAX+1)*0;
>>>> return zero;
>>>> }
>>>>
>>>> int
>>>> main(){
>>>> return 0;
>>>> }
>>>>
>>>> This program does not transgress the bounds of undefined behavior.
>>
>>To clarify, the comments in my posting were meant to be read as
>>saying the given text is the entire program, and that it is strictly
>>conforming with respect to conforming hosted implementations.
>>(Incidentally, given the rules for freestanding implementations, I'm
>>not sure that it is even possible for any program to be strictly
>>conforming with respect to conforming freestanding implementations.
>>In any case my statements were meant only in the context of hosted
>>implementations.)
>
> Ok.
>
>>> [snip]
>>> Perhaps you mean that this is irrelevant because `foo` is not
>>> invoked, but I see no reason why that need be the case in e.g.
>>> a freestanding environment.
>>
>>I explained the context of my previous statements above. Sorry for
>>not saying that in the original message.
>>
>>> In a hosted environment, I don't
>>> think anything explicitly prevents `foo` from being called after
>>> `main` returns (though I can't imagine that would happen in real
>>> life; it would be weird if it did).
>>
>>The semantics described in the ISO C standard don't admit that
>>possibility.
>
> Could you please point to where it says this, in the C standard?
>
> I cannot find anything that says that arbitrary code cannot run
> after `main()` returns, and I don't see how that could possibly
> be true.
N3220 5.1.2.4, Program semantics.
It defines the *observable behavior* of a program, which consists of
accesses to volatile objects, data written to files, and I/O dynamics of
interactive devices.
If the usual "Hello, world" program prints "Hello, world" followed
by "Goodbye", the implementation is non-conforming. If it formats
my hard drive after printing "Goodbye", it's non-conforming and
dangerous.
>>Whether foo() has external linkage or internal
>>linkage doesn't change that.
>
> I disagree. There's no possible way for the implementation to
> know whether a function with external linkage will be ultimately
> invoked or not; consider a system that supports loadable shared
> modules. Nothing prevents even this simple program from being
> compiled as a shared module, dynamically loaded, the loading
> program explicitly searching for and finding the symbol
> corresponding to the `foo` function, and invoking it.
Remember that linking is translation phase 8. The compiler is not
the entire implementation.
> Hence, the compiler _must_ treat with UB as written, which is
> why `ubsan` inserts trapping code in `foo`.
I don't know what "_must_ treat with UB" means.
foo() has undefined behavior if it's called, so replacing its
body with trapping code is valid. But (I'm reasonably sure that)
an implementation cannot reject a program just because it can't
prove that it has no undefined behavior during execution. It can
reject it if it can prove that it *always* has undefined behavior
during execution.
> In your example, `foo` clearly exhibits UB; I think your
> argument is whether that has a realized effect or not, since the
> UB is not invoked. I'm saying that in general a compiler cannot
> possibly know that when it compiles `foo`, and is free to assume
> the worst.
foo() exhibits UB if and only if it's called during execution.
Yes, a compiler can't know whether foo() will be called.
An implementation, particularly a linker, might know, but is not
required to. No, it is not free to assume the worst.
I certainly wouldn't want a compiler to reject `1/time(NULL)`
because it can't prove that time(NULL) won't be zero, or reject
`argc+1` because it can't prove that argc < INT_MAX. Code whose
behavior would be undefined if it were executed has no behavior
(and therefore no UB) if it's not executed.
[...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-04 23:49 +0000 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <10vt2un$fuu$1@reader1.panix.com> |
| In reply to | #399710 |
In article <10vsnl7$lkmu$1@kst.eternal-september.org>,
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>> In article <865x3yd21n.fsf@linuxsc.com>,
>> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>>>> In article <86ik81cfk5.fsf_-_@linuxsc.com>,
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>[...]
>>>>> There's an important distinction to make here. Consider this
>>>>> program:
>>>>>
>>>>> #include <limits.h>
>>>>>
>>>>> int
>>>>> foo(){
>>>>> int zero = (INT_MAX+1)*0;
>>>>> return zero;
>>>>> }
>>>>>
>>>>> int
>>>>> main(){
>>>>> return 0;
>>>>> }
>>>>>
>>>>> This program does not transgress the bounds of undefined behavior.
>>>
>>>To clarify, the comments in my posting were meant to be read as
>>>saying the given text is the entire program, and that it is strictly
>>>conforming with respect to conforming hosted implementations.
>>>(Incidentally, given the rules for freestanding implementations, I'm
>>>not sure that it is even possible for any program to be strictly
>>>conforming with respect to conforming freestanding implementations.
>>>In any case my statements were meant only in the context of hosted
>>>implementations.)
>>
>> Ok.
>>
>>>> [snip]
>>>> Perhaps you mean that this is irrelevant because `foo` is not
>>>> invoked, but I see no reason why that need be the case in e.g.
>>>> a freestanding environment.
>>>
>>>I explained the context of my previous statements above. Sorry for
>>>not saying that in the original message.
>>>
>>>> In a hosted environment, I don't
>>>> think anything explicitly prevents `foo` from being called after
>>>> `main` returns (though I can't imagine that would happen in real
>>>> life; it would be weird if it did).
>>>
>>>The semantics described in the ISO C standard don't admit that
>>>possibility.
>>
>> Could you please point to where it says this, in the C standard?
>>
>> I cannot find anything that says that arbitrary code cannot run
>> after `main()` returns, and I don't see how that could possibly
>> be true.
>
>N3220 5.1.2.4, Program semantics.
>
>It defines the *observable behavior* of a program, which consists of
>accesses to volatile objects, data written to files, and I/O dynamics of
>interactive devices.
Yes, but it does so for strictly-conforming programs with no UB.
To understand conformance, we have to jump over to section 4,
which explicitly says that, 'Undefined behavior is otherwise
indicated in this document by the words "undefined behavior" or
by the omission of any explicit definition of behavior.' As it
does not say that a program with an instance of undefined
behavior in an integer constant expression that is not executed
must otherwise behave in any given manner, what the program does
is undefined. A constaint violation mandates a diagnostic, but
beyond that, the standard is (AFAICT) silent.
Undefined Behavior, in turn, is not defined as specific only to
execution: the standard simply says that it is "behavior, upon
use of a *nonportable or erroneous program construct*..." for
which there are no requirements, and there are examples of
things that are explicitly UB at translation time, such as
improperly terminated lexemes and so forth.
Furthermore, the expression above is obviously an integer
constant expression as defined by sec 6.6 para 8. Section 6.6,
para 4, reads in part, "Each constant expression shall evaluate
to a constant that is in the range of representable values for
its type." The expression, `(INT_MAX+1)*0` violates this
constraint, and so therefore a diagnostic is mandated as per
sec 5.1.1.3 para 1. That it appears in code that is not
obviously called from `main` doesn't change that.
Morever, sec 6.6 para 17 says that, "the semantic rules for
evaluation of a constant expression are the same as for
nonconstant expressions." This brings us back to 5.1.2.4,
though I submit that para (4) is a stronger argument for what
you and Tim are saying, as it reads in part, "An actual
implementation is not required to evaluate part of an expression
if it can deduce that its value is not used and that no needed
side effects are produced (including any caused by calling a
function or through volatile access to an object)." I interpret
this to mean that, if the implementation can determine that
there is no way that `foo` can be called, it does not _have_ to
evaluate the above expression. However, it must satisfy the
range constraint from section 6.6, so it likely will, and in any
event, the standard does not say that it, "shall not" evaluate
it, or when.
Once the compiler does that, if it does, and observes UB, the
standard is silent on what requirements it imposes, which means
the behavior is undefined. I see no reason it couldn't arrange
to invoke `foo` at that point.
So no, I do not see how execution according to the rules of the
abstract machine is not guaranteed, here. I certainly see no
way in which this can be regarded as a strictly conforming
program.
>If the usual "Hello, world" program prints "Hello, world" followed
>by "Goodbye", the implementation is non-conforming. If it formats
>my hard drive after printing "Goodbye", it's non-conforming and
>dangerous.
Two separate things. My point earlier was that code can
obviously run after `main` terminates. Moreoever, I can't
imagine what would _prevent_ a runtime system that invokes
`main` from doing something like printing, "PROGRAM STOPPED"
after `main` returned. C imposes no requirements here.
Whether `foo` could be invoked after, I think, is undefined.
>>>Whether foo() has external linkage or internal
>>>linkage doesn't change that.
>>
>> I disagree. There's no possible way for the implementation to
>> know whether a function with external linkage will be ultimately
>> invoked or not; consider a system that supports loadable shared
>> modules. Nothing prevents even this simple program from being
>> compiled as a shared module, dynamically loaded, the loading
>> program explicitly searching for and finding the symbol
>> corresponding to the `foo` function, and invoking it.
>
>Remember that linking is translation phase 8. The compiler is not
>the entire implementation.
Exactly my point. The compiler cannot know how `foo` might be
used, or how the translated object might be exercised. There's
I don't see how it could possibly know that, given that `foo`
has external linkage.
>> Hence, the compiler _must_ treat with UB as written, which is
>> why `ubsan` inserts trapping code in `foo`.
>
>I don't know what "_must_ treat with UB" means.
>
>foo() has undefined behavior if it's called, so replacing its
>body with trapping code is valid. But (I'm reasonably sure that)
>an implementation cannot reject a program just because it can't
>prove that it has no undefined behavior during execution. It can
>reject it if it can prove that it *always* has undefined behavior
>during execution.
What I'm saying is that, `foo` has undefined behavior _period_.
That's manifest in an integer constant expression, whether it is
executed at runtime or not. I believe that the standard forces
the expression to be evaluated at translation time, via the
"shall" mandate when checking the constraint on the range in sec
6.6 para 4. Further, that evaluation must happen in accordance
with the rules of the abstract machine, as per 5.1.2.4 para 17.
The diagnostic is mandated, as is the translation-time
evaluation. The expression is itself manifestly exhibits UB,
and so therefore the result of the rest of the translation is
undefined.
I could be wrong; this is all excessively pedantic. And of
course, if an implementation does something silly and emits
garbage for Tim's program, then I argue it should be chucked
onto the dustbin of excessive fawning over the standard. But
I'm not convinced that the standard _prohibits_ such an extreme
interpretation.
>> In your example, `foo` clearly exhibits UB; I think your
>> argument is whether that has a realized effect or not, since the
>> UB is not invoked. I'm saying that in general a compiler cannot
>> possibly know that when it compiles `foo`, and is free to assume
>> the worst.
>
>foo() exhibits UB if and only if it's called during execution.
>
>Yes, a compiler can't know whether foo() will be called.
>An implementation, particularly a linker, might know, but is not
>required to. No, it is not free to assume the worst.
See above.
>I certainly wouldn't want a compiler to reject `1/time(NULL)`
>because it can't prove that time(NULL) won't be zero, or reject
>`argc+1` because it can't prove that argc < INT_MAX. Code whose
>behavior would be undefined if it were executed has no behavior
>(and therefore no UB) if it's not executed.
That's categorically different; what you are describing are what
Regehr calls, "Type-2" functions, and I agree with you for
those.
The program that Tim posted has a "Type-3" function, and
constraints dictate that the UB express must be evaluated at
translation time, and a diagnostic emitted. In the most
charitable interpretation, it cannot be considered a strictly
conforming program, even if the implementation is smart enough
to avoid evaluating the constant expression, as it is
unspecified whether it's evaluated or not, and strictly
conforming programs shall not rely on unspecified behavior.
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-06-04 18:04 -0700 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <10vt7b9$pi3s$1@kst.eternal-september.org> |
| In reply to | #399725 |
cross@spitfire.i.gajendra.net (Dan Cross) writes:
> In article <10vsnl7$lkmu$1@kst.eternal-september.org>,
> Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>>> In article <865x3yd21n.fsf@linuxsc.com>,
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>>>>cross@spitfire.i.gajendra.net (Dan Cross) writes:
>>>>> In article <86ik81cfk5.fsf_-_@linuxsc.com>,
>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>>[...]
>>>>>> There's an important distinction to make here. Consider this
>>>>>> program:
>>>>>>
>>>>>> #include <limits.h>
>>>>>>
>>>>>> int
>>>>>> foo(){
>>>>>> int zero = (INT_MAX+1)*0;
>>>>>> return zero;
>>>>>> }
>>>>>>
>>>>>> int
>>>>>> main(){
>>>>>> return 0;
>>>>>> }
>>>>>>
>>>>>> This program does not transgress the bounds of undefined behavior.
>>>>
>>>>To clarify, the comments in my posting were meant to be read as
>>>>saying the given text is the entire program, and that it is strictly
>>>>conforming with respect to conforming hosted implementations.
>>>>(Incidentally, given the rules for freestanding implementations, I'm
>>>>not sure that it is even possible for any program to be strictly
>>>>conforming with respect to conforming freestanding implementations.
>>>>In any case my statements were meant only in the context of hosted
>>>>implementations.)
>>>
>>> Ok.
>>>
>>>>> [snip]
>>>>> Perhaps you mean that this is irrelevant because `foo` is not
>>>>> invoked, but I see no reason why that need be the case in e.g.
>>>>> a freestanding environment.
>>>>
>>>>I explained the context of my previous statements above. Sorry for
>>>>not saying that in the original message.
>>>>
>>>>> In a hosted environment, I don't
>>>>> think anything explicitly prevents `foo` from being called after
>>>>> `main` returns (though I can't imagine that would happen in real
>>>>> life; it would be weird if it did).
>>>>
>>>>The semantics described in the ISO C standard don't admit that
>>>>possibility.
>>>
>>> Could you please point to where it says this, in the C standard?
>>>
>>> I cannot find anything that says that arbitrary code cannot run
>>> after `main()` returns, and I don't see how that could possibly
>>> be true.
>>
>>N3220 5.1.2.4, Program semantics.
>>
>>It defines the *observable behavior* of a program, which consists of
>>accesses to volatile objects, data written to files, and I/O dynamics of
>>interactive devices.
>
> Yes, but it does so for strictly-conforming programs with no UB.
It does so for programs in general, not just strictly conforming
ones. If a program has undefined behavior, all bets are off,
but for example a program that evaluates `printf("%d\n", INT_MAX)`
is not strictly conforming, but it's fully subject to 5.1.2.4.
> To understand conformance, we have to jump over to section 4,
> which explicitly says that, 'Undefined behavior is otherwise
> indicated in this document by the words "undefined behavior" or
> by the omission of any explicit definition of behavior.' As it
> does not say that a program with an instance of undefined
> behavior in an integer constant expression that is not executed
> must otherwise behave in any given manner, what the program does
> is undefined. A constaint violation mandates a diagnostic, but
> beyond that, the standard is (AFAICT) silent.
I don't think an integer constant expression can have undefined
behavior. INT_MAX+1 and 1/0 are not constant expressions, because
neither "evaluate(s) to a constant that is in the range of
representable values for its type".
I claim that an expression that looks like a constant expression
*isn't* a constant-expression if it doesn't appear in a context
that requires a constant-expression.
The program in question, quoted above, has:
int zero = (INT_MAX+1)*0;
`(INT_MAX+1)*0` is not a constant expression, not because of the
overflow, but because a constant expression is not required in
that context. "constant-expression" is defined by a production in
the grammar (it reduces to "conditional-expression"). Even in
int n = 42;
42 is not a a constant expression, because the grammar doesn't
call for a constant expression in that context -- even though it
looks like one. Similarly, in `a + b * c`, `a + b` looks like an
additive expression, but it isn't one. (Not a perfect analogy.)
> Undefined Behavior, in turn, is not defined as specific only to
> execution: the standard simply says that it is "behavior, upon
> use of a *nonportable or erroneous program construct*..." for
> which there are no requirements, and there are examples of
> things that are explicitly UB at translation time, such as
> improperly terminated lexemes and so forth.
Yes, there are constructs that are explicitly UB at translation time.
(I think that's unfortunate, and there are efforts to clear up some
such cases in C2y.)
Signed integer overflow is not one of those constructs.
Any undefined behavior from evaluating INT_MAX+1 happens during
execution (barring constraint violations).
> Furthermore, the expression above is obviously an integer
> constant expression as defined by sec 6.6 para 8. Section 6.6,
> para 4, reads in part, "Each constant expression shall evaluate
> to a constant that is in the range of representable values for
> its type." The expression, `(INT_MAX+1)*0` violates this
> constraint, and so therefore a diagnostic is mandated as per
> sec 5.1.1.3 para 1. That it appears in code that is not
> obviously called from `main` doesn't change that.
It satisfies the requirements for an integer constant expression in
6.6p8, but it violates the constraint in 6.6p4. (I presume that an
"integer constant expression" must be a "constant expression".)
But since "constant-expression" is a grammatical production,
it doesn't have to satisfy that constraint, and no diagnostic
is required. (A warning is certainly permitted.)
Similarly, this:
int n = INT_MAX + 1;
at block scope doesn't require a diagnostic, though of course it
has undefined behavior -- but at file scope, the initializer is a
constant expression, so that would be a constraint violation.
> Morever, sec 6.6 para 17 says that, "the semantic rules for
> evaluation of a constant expression are the same as for
> nonconstant expressions." This brings us back to 5.1.2.4,
> though I submit that para (4) is a stronger argument for what
> you and Tim are saying, as it reads in part, "An actual
> implementation is not required to evaluate part of an expression
> if it can deduce that its value is not used and that no needed
> side effects are produced (including any caused by calling a
> function or through volatile access to an object)." I interpret
> this to mean that, if the implementation can determine that
> there is no way that `foo` can be called, it does not _have_ to
> evaluate the above expression. However, it must satisfy the
> range constraint from section 6.6, so it likely will, and in any
> event, the standard does not say that it, "shall not" evaluate
> it, or when.
Overflow in a constant expression is not undefined behavior. It's a
constraint violation. But that doesn't apply here, because the
initializer is not a constant expression. (Sorry if I'm repeating
myself.)
> Once the compiler does that, if it does, and observes UB, the
> standard is silent on what requirements it imposes, which means
> the behavior is undefined. I see no reason it couldn't arrange
> to invoke `foo` at that point.
Any UB in the program would occur during execution, and in fact
it *won't* occur during execution because foo() isn't called.
A compiler can't generate code with arbitrary behavior just because
it can't prove that there will be no UB. If it could, every signed
or floating-point arithmetic operation with unknown operand values
would grant the same permission.
> So no, I do not see how execution according to the rules of the
> abstract machine is not guaranteed, here. I certainly see no
> way in which this can be regarded as a strictly conforming
> program.
foo()'s behavior would be undefined if it were called. It *isn't*
called, so there's no actual UB. The program does not violate any
of the other requirements for strict conformance.
>>If the usual "Hello, world" program prints "Hello, world" followed
>>by "Goodbye", the implementation is non-conforming. If it formats
>>my hard drive after printing "Goodbye", it's non-conforming and
>>dangerous.
>
> Two separate things. My point earlier was that code can
> obviously run after `main` terminates. Moreoever, I can't
> imagine what would _prevent_ a runtime system that invokes
> `main` from doing something like printing, "PROGRAM STOPPED"
> after `main` returned. C imposes no requirements here.
Yes, it does. An OS can print "PROGRAM STOPPED", but not as part
of the execution of the program. On my system, a shell prompt is
printed after a program terminates, but not by the program. If I
execute a "hello, world" program with its output redirected to a file
(on a system that supports that), the resulting file cannot contain
"PROGRAM STOPPED". The requirements in 5.1.2.4 specify both what
the execution of a program must do and what it must not do.
> Whether `foo` could be invoked after, I think, is undefined.
>
>>>>Whether foo() has external linkage or internal
>>>>linkage doesn't change that.
>>>
>>> I disagree. There's no possible way for the implementation to
>>> know whether a function with external linkage will be ultimately
>>> invoked or not; consider a system that supports loadable shared
>>> modules. Nothing prevents even this simple program from being
>>> compiled as a shared module, dynamically loaded, the loading
>>> program explicitly searching for and finding the symbol
>>> corresponding to the `foo` function, and invoking it.
>>
>>Remember that linking is translation phase 8. The compiler is not
>>the entire implementation.
>
> Exactly my point. The compiler cannot know how `foo` might be
> used, or how the translated object might be exercised. There's
> I don't see how it could possibly know that, given that `foo`
> has external linkage.
We were presented with a complete translation unit that included a
function definition for "main". It's a complete program. There's no
valid way for some other program to call foo. If OS provided such
a mechanism, it would be outside the scope of C.
>>> Hence, the compiler _must_ treat with UB as written, which is
>>> why `ubsan` inserts trapping code in `foo`.
>>
>>I don't know what "_must_ treat with UB" means.
>>
>>foo() has undefined behavior if it's called, so replacing its
>>body with trapping code is valid. But (I'm reasonably sure that)
>>an implementation cannot reject a program just because it can't
>>prove that it has no undefined behavior during execution. It can
>>reject it if it can prove that it *always* has undefined behavior
>>during execution.
>
> What I'm saying is that, `foo` has undefined behavior _period_.
> That's manifest in an integer constant expression, whether it is
> executed at runtime or not. I believe that the standard forces
> the expression to be evaluated at translation time, via the
> "shall" mandate when checking the constraint on the range in sec
> 6.6 para 4. Further, that evaluation must happen in accordance
> with the rules of the abstract machine, as per 5.1.2.4 para 17.
> The diagnostic is mandated, as is the translation-time
> evaluation. The expression is itself manifestly exhibits UB,
> and so therefore the result of the rest of the translation is
> undefined.
foo is a function. foo does not have undefined behavior; it has no
behavior at all. A *call* to foo during execution has undefined
behavior. (`foo;` is a statement-expression that does nothing;
it does not have undefined behavior.)
[SNIP]
I think the question of whether the initializer is a
constant-expression or not has caused some not entirely relevant
confusion.
Here's another example that avoids that issue.
#include <limits.h>
int foo(void) {
int zero;
zero = INT_MAX;
zero ++;
zero *= 0;
return zero;
}
int main(void) {
return 0;
}
Given my grammatical argument above, I would say that this program
has no constant expressions. Whether that argument is correct or
not, it certainly has no constant expressions that violate any
constraint or that have undefined behavior. Evaluating `zero ++`
(which doesn't even pretend to be a constant expression) would have
run-time undefined behavior -- *if* foo() were ever called.
And given this translation unit, I don't think there's any way to
construct a multi-TU program that calls foo, so a compiler *can*
determine that foo is never called (but there's no requirement to
do so, or to make any use of that information).
--
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 | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-06-05 10:41 +0200 |
| Subject | Re: Constants and undefined behavior |
| Message-ID | <10vu236$fm4o$4@dont-email.me> |
| In reply to | #399725 |
On 2026-06-05 01:49, Dan Cross wrote: >> [...] > [...] > [ ... (INT_MAX+1)*0 ] > Furthermore, the expression above is obviously an integer > constant expression as defined by sec 6.6 para 8. Section 6.6, > para 4, reads in part, "Each constant expression shall evaluate > to a constant that is in the range of representable values for > its type." The expression, `(INT_MAX+1)*0` violates this > constraint, and so therefore a diagnostic is mandated as per > sec 5.1.1.3 para 1. That it appears in code that is not > obviously called from `main` doesn't change that. I'm curious about that "violation"; a violation would require (at least) two sorts of logical preconditions. - The first is that all *sequentially* (literally) evaluated sub-expression values are representable as value - INT_MAX+1 certainly can't be represented in generated code that conforms to the abstract *mathematical* value - but is that necessary if _the whole_ expression is (mathematically) just 0 (because of the final factor). And the second (related) is whether the order of the sub-expression evaluation is relevant; if we'd assume the expression evaluation to be considered from right to left then it would be irrelevant what's inside the parenthesis. From the standard quotes I cannot really recognize that these preconditions, how to determine UB/errors/violations, would be necessary. I'm no native speaker and I fear my question as formulated was hard to understand. It's basically the question of the standard implying (INT_MAX+1)*0 to be analyzed sequentially as written or whether it could as well analyze it from right to left and thus recognizing no problem, since from the mathematical view - but also practically - a concrete representable value of a here irrelevant sub-expression isn't necessary. Or another try of a (paraphrased) formulation; for the determination of constraint violations does the expression have strict (sort of) sequencing points _after each term_ (and each left-to-right sub-expression has to be well-defined) or can it be valued/analyzed as a whole not putting any preconditions about evaluation order etc. when determining the overall value? Janis PS: One yet non-considered question that was part of my original post was: "Is there any rationale from the _software designer_'s perspective?" > [...]
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-06-02 05:35 -0700 |
| Message-ID | <10vmimv$2tjoi$3@kst.eternal-september.org> |
| In reply to | #399608 |
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
> On 2026-06-01 00:54, Keith Thompson wrote:
>>> [...]
>> Yes, a compiler can reduce (a + b) * 0 to just 0. But it's not
>> required to do so, and (INT_MAX + 1) * 0 still has undefined
>> behavior. Undefined behavior is determined by the rules of the
>> abstract machine *without* any adjustments permitted by the as-if
>> rule.
>
> This is something I really don't get in the actual C-logic...
>
> Using constants that can be determined at compile time is UB here,
> despite the '* 0' mathematically indicating an IMO clear semantics,
> but using variables is only UB possibly at runtime? And despite all
> that the latter might not even get triggered because it's probably
> optimized away? - I can't help, this sounds really crude.
>
> Is there any rationale from the _software designer_'s perspective?
In the abstract machine, every operator and subexpression is
evaluated (barring things like "||", "&&", and "?:"). (INT_MAX + 1)
has undefined behavior due to overflow, therefore any expression
that has (INT_MAX + 1) as a subexpression has undefined behavior.
Replacing (expr * 0) by 0 is an optimization, and optimizations
are *optional*. A naive implementation could generate code that
peforms the addition and the muliplication by 0; if the addition
traps, it traps.
Note that in a context that requires a constant expression, overflow is
a constraint violation. For example, a case label like:
case (INT_MAX + 1) * 0:
must be diagnosed at compile time.
--
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 | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2026-06-02 06:29 -0700 |
| Message-ID | <86ecipcbqa.fsf@linuxsc.com> |
| In reply to | #399618 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: > Note that in a context that requires a constant expression, overflow is > a constraint violation. For example, a case label like: > > case (INT_MAX + 1) * 0: > > must be diagnosed at compile time. gcc disagrees with you.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-06-02 16:10 +0200 |
| Message-ID | <10vmo8n$2ruaa$3@dont-email.me> |
| In reply to | #399625 |
On 02/06/2026 15:29, Tim Rentsch wrote: > Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: > >> Note that in a context that requires a constant expression, overflow is >> a constraint violation. For example, a case label like: >> >> case (INT_MAX + 1) * 0: >> >> must be diagnosed at compile time. > > gcc disagrees with you. My testing shows all versions of gcc that I tested on godbolt gave a warning, even without any options. I don't believe that INT_MAX can have any type suffixes that would avoid the overflow. What version of gcc and/or flags let that case label pass without a diagnostic? (I don't know if Keith is correct about it being a constraint violation - I have not looked at the details there.)
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-06-02 15:29 -0700 |
| Message-ID | <10vnlgu$382un$2@kst.eternal-september.org> |
| In reply to | #399625 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> Note that in a context that requires a constant expression, overflow is
>> a constraint violation. For example, a case label like:
>>
>> case (INT_MAX + 1) * 0:
>>
>> must be diagnosed at compile time.
>
> gcc disagrees with you.
What makes you think so?
$ cat c.c
#include <limits.h>
int main(void) {
switch (0) {
case (INT_MAX + 1) * 0:
break;
}
}
$ gcc -std=c17 -pedantic-errors -c c.c
c.c: In function ‘main’:
c.c:4:23: warning: integer overflow in expression of type ‘int’ results in ‘-2147483648’ [-Woverflow]
4 | case (INT_MAX + 1) * 0:
| ^
c.c:4:9: error: overflow in constant expression [-Woverflow]
4 | case (INT_MAX + 1) * 0:
| ^~~~
$
But taking a closer look at the standard, I'm not 100% sure that the
language requires a diagnostic, though I think that's the intent.
The relevant constraint is:
Each constant expression shall evaluate to a constant that is
in the range of representable values for its type.
If I squint really hard, I can argue that the entire expression
has to be a constant expression, but it doesn't say that its
subexpressions are constant expressions -- and *if* INT_MAX +
1 evaluates to INT_MIN in the current implementation, then
(INT_MAX + 1) * 0 evaluates to 0 and therefore satisfies the
constraint.
But INT_MAX + 1 could legally trap, for example, and I don't believe
it was intended that a given expression can be a constant expression
or not depending on the vagaries of the behavior of an instance
of UB.
--
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 | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2026-06-05 06:41 -0700 |
| Message-ID | <86bjdpayv0.fsf@linuxsc.com> |
| In reply to | #399652 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: > Tim Rentsch <tr.17687@z991.linuxsc.com> writes: > >> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes: >> >>> Note that in a context that requires a constant expression, overflow is >>> a constraint violation. For example, a case label like: >>> >>> case (INT_MAX + 1) * 0: >>> >>> must be diagnosed at compile time. >> >> gcc disagrees with you. > > What makes you think so? > > [...] I'm skipping this and proceeding on to the original question. > But taking a closer look at the standard, I'm not 100% sure that the > language requires a diagnostic, though I think that's the intent. > The relevant constraint is: > > Each constant expression shall evaluate to a constant that is > in the range of representable values for its type. > > If I squint really hard, I can argue that the entire expression > has to be a constant expression, but it doesn't say that its > subexpressions are constant expressions -- and *if* INT_MAX + > 1 evaluates to INT_MIN in the current implementation, then > (INT_MAX + 1) * 0 evaluates to 0 and therefore satisfies the > constraint. My reasoning is as follows. To determine if the constraint is satisfied, the compiler must first evaluate the expression (INT_MAX + 1) * 0. To evaluate the expression (INT_MAX + 1) * 0, the compiler must first evaluate the sub-expression (INT_MAX + 1). Because the expression (INT_MAX + 1) overflows, the behavior is undefined, and the compiler is free to decide that the value of the sub-expression (INT_MAX + 1) is, let's say, 12. The compiler next evaluates the overall expression as 12*0, which is 0 (an int). This result of the overall expression satisfies the constraint, and so the compiler is not obliged to generate a diagnostic. Going back, when evaluating (INT_MAX + 1), the compiler could have decided to choose the value 3.14159e47. In that case the value of the overall expression would be 0.0. This value has type double, which does not satisfy the constraint that the result have integer type. Thus if the compiler had made this decision then a diagnostic would be required. Overall conclusion: whether a diagnostic is required depends on what behavior is chosen for the construct (INT_MAX + 1). The implementation could choose a behavior where the constraint is satisfied, or it could choose a behavior where the constraint is not satisfied. > But INT_MAX + 1 could legally trap, for example, and I don't > believe it was intended that a given expression can be a constant > expression or not depending on the vagaries of the behavior of an > instance of UB. I see no basis for this belief. My conclusions are based on what the C standard actually says, rather than guesses about some unstated "intentions". I think you would do well to reach your conclusions based more on the actual text of the C standard, and less on your interpretation of what the text was "intended" to mean.
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2026-06-02 13:59 -0700 |
| Message-ID | <10vng7e$377sq$1@dont-email.me> |
| In reply to | #399569 |
On 5/31/2026 3:54 PM, Keith Thompson wrote: > David Brown <david.brown@hesbynett.no> writes: >> On 31/05/2026 16:24, James Kuyper wrote: >>> On 2026-05-31 07:18, David Brown wrote: > [...] >>>> People might think they affect the order of evaluation, such as when you >>>> have function calls : >>>> >>>> u = foo(x) + (foo(y) + foo(z)); >>>> >>>> Some people might think the use of parentheses means that "foo(y)" and >>>> "foo(z)" are called before "foo(x)", when the order of all these calls >>>> (and the additions) is unspecified. (Again, a given compiler might be >>>> influenced by the parentheses, but the language does not require it. >>> >>> You're correct with regard to the function calls, but the >>> parenthesized addition must be performed first, and the other one >>> second, which may make a difference, for the same reasons given in my >>> previous paragraph. >> >> The parentheses do not dictate the order of evaluation. But you are >> correct - and it's worth pointing out, so thank you for doing that - >> that for floating point operations, the grouping of operations can >> affect the result. > > The parentheses do not dictate the order of evaluation *of the > operands*. Each "+" can be evaluated (the addition performed) > only after the values of its operands are known. But regardless > of parentheses or operator precedence, the three operands foo(x), > foo(y), and foo(z) can be evaluated in any of 6 possible orders. > (It's different when you have operations like "&&", "||", and ",", > which imposes additional sequence points.) > >> If you are talking about floating point arithmetic (I was thinking of >> integer arithmetic, but did not specify), then the operations are not >> necessarily commutative or associative, and the compiler cannot then >> re-arrange the operations unless it knows that doing so does not >> affect the result. > > It's not just floating-point. Signed integer overflow is also relevant. > > (INT_MIN + INT_MAX) + 1 is well defined. (INT_MIN + INT_MAX) +1 > is equivalent, and is also well defined. INT_MIN + (INT_MAX +1) > has undefined behavior. > >> But except for specific cases, the order of evaluation - both for the >> values and side-effects - of sub-expressions is unspecified. Indeed, >> they are unsequenced - the evaluations can interleave. >> >> Usually, both sub-expressions of a binary operator will be evaluated >> before the operator itself, simply because usually the results of the >> operator cannot be calculated until the sub-expression's values are >> known. But this is not a requirement of the language - if the >> compiler can get the same results without doing so, it is free to pick >> a different order. "(a + b) * 0" does not need to evaluate "a", "b", >> or "a + b" at all unless there is a possibility of a side-effect - and >> it can perform the side-effects in any order. "a + (b + c)" can check >> "a" for a trap representation and deal with that before looking at "b" >> and "c" or the results of "b + c", even though it cannot (for floating >> point operations) re-arrange the code to do "a + b" first. > > Yes, a compiler can reduce (a + b) * 0 to just 0. But it's not > required to do so, and (INT_MAX + 1) * 0 still has undefined > behavior. Undefined behavior is determined by the rules of the > abstract machine *without* any adjustments permitted by the as-if > rule. > > [...] > 10 + 5 - 7 + 3 Oh my this is an error for the programmers logic! they forgot to do: 10 + 5 - (7 + 3) ?
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-02 13:05 +0000 |
| Message-ID | <10vmke4$4bm$1@reader1.panix.com> |
| In reply to | #399550 |
In article <10vh1eo$1ei50$2@dont-email.me>, Bart <bc@freeuk.com> wrote:
>On 31/05/2026 10:49, David Brown wrote:
>> On 31/05/2026 10:12, Richard Harnden wrote:
>>> On 31/05/2026 00:43, Keith Thompson wrote:
>>>> C's operator precedence rules are complicated and arguably flawed.
>>>> They could have been defined differently. A simpler set of rules,
>>>> with fewer levels,*might* have been better. I don't have any
>>>> concrete suggestions -- nor do I have any strong preferences.
>>>> I accept C's rules as they are. I would accept them if they had
>>>> been defined differently.
>>>
>>> Can't the compiler easily remove any parens that aren't necessary?
>>> So - just write complex expressions in a way that a human can most
>>> easily understand, it makes your intention clear and probable doesn't
>>> increase the size of the executable.
>>
>> Of course. Parentheses do not affect the generated code unless they
>> affect the semantics of the expression. (Some people think parentheses
>> affect the order of evaluation,
>
>They can do if they make a expression be parsed differently. Do you have
>an example where they make no difference but people might think they do?
This is all a bit of a distraction from the original point that
David and Richard Harnden were trying to make, which seemed
clear enough to me, but perhaps should have been given with a
better example. Maybe something like:
d = a*b + c;
Is equivalent to,
d = (a*b) + c;
And in this case, the parentheses are superfluous and don't
change the order of evaluation of the expression as far as the
language is concerned. Whether a compiler rearranges it in
generated code in a way that is more convenient of faster or
whatever is another matter.
I would quibble with this idea that the compiler "removes"
parentheses. I get the intuition, but C is not Go where the
compiler "inserts" semi-colons for you, and has no analogous
concept. Rather, as I think Keith said, expressions are parsed
into some internal representation, and then transformed into
something like an abstract syntax tree, where syntactic
notations like parentheses are lost.
Both expressions above correspond to an AST like:
┌───────┐
│BinOp +│
└───────┘
╱ ╲
╱ ╲
┌───────┐ ┌───────┐
│BinOp *│ │Sym `c`│
└───────┘ └───────┘
╱ ╲
╱ ╲
┌───────┐ ┌───────┐
│Sym `a`│ │Sym `b`│
└───────┘ └───────┘
But the to get to that, it may be that the compiler uses a
different initial representation, like a parse tree that more
closely resembles the source language grammar. Here, the
two expressions might have different parsed representations.
E.g., for the first, simplifying heavily, may look something
like this:
┌──────┐
│ expr │
└──────┘
╱ │ ╲
╱ │ ╲
┌─────┐ . ┌─────┐
│term │ (+) │term │
└─────┘ ' └─────┘
╱ │ ╲ │
╱ │ ╲ │
┌─────┐ . ┌─────┐ ┌─────┐
│ident│ (*) │ident│ │ident│
└─────┘ ' └─────┘ └─────┘
│ │ │
│ │ │
.─. .─. .─.
(`a`) (`b`) (`c`)
`─' `─' `─'
While the second might add an extra `expr` node, as in:
┌──────┐
│ expr │
└──────┘
╱ │ ╲
╱ │ ╲
┌──────┐ . ┌─────┐
│ expr │ (+) │term │
└──────┘ ' └─────┘
│ │
│ │
┌─────┐ ┌─────┐
│term │ │ident│
└─────┘ └─────┘
╱ │ ╲ │
╱ │ ╲ │
┌─────┐ . ┌─────┐ .─.
│ident│ (*) │ident│ (`c`)
└─────┘ ' └─────┘ `─'
│ │
│ │
.─. .─.
(`a`) (`b`)
`─' `─'
I believe that the answer, for most compilers that parse and
then convert to an AST, the second is more likely to be created
than the first. However, given that the same AST is created
from both parse trees, this is unlikely to have an effect on the
object code ultimately output from the compiler.
- Dan C.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2026-06-02 14:38 +0100 |
| Subject | Parentheses (was: this girl calls c ugly) |
| Message-ID | <10vmmc2$2utb2$2@dont-email.me> |
| In reply to | #399623 |
On 02/06/2026 14:05, Dan Cross wrote: > In article <10vh1eo$1ei50$2@dont-email.me>, Bart <bc@freeuk.com> wrote: >> On 31/05/2026 10:49, David Brown wrote: >>> On 31/05/2026 10:12, Richard Harnden wrote: >>>> On 31/05/2026 00:43, Keith Thompson wrote: >>>>> C's operator precedence rules are complicated and arguably flawed. >>>>> They could have been defined differently. A simpler set of rules, >>>>> with fewer levels,*might* have been better. I don't have any >>>>> concrete suggestions -- nor do I have any strong preferences. >>>>> I accept C's rules as they are. I would accept them if they had >>>>> been defined differently. >>>> >>>> Can't the compiler easily remove any parens that aren't necessary? >>>> So - just write complex expressions in a way that a human can most >>>> easily understand, it makes your intention clear and probable doesn't >>>> increase the size of the executable. >>> >>> Of course. Parentheses do not affect the generated code unless they >>> affect the semantics of the expression. (Some people think parentheses >>> affect the order of evaluation, >> >> They can do if they make a expression be parsed differently. Do you have >> an example where they make no difference but people might think they do? > > This is all a bit of a distraction from the original point that > David and Richard Harnden were trying to make, which seemed > clear enough to me, but perhaps should have been given with a > better example. Maybe something like: > > d = a*b + c; > > Is equivalent to, > > d = (a*b) + c; > > And in this case, the parentheses are superfluous and don't > change the order of evaluation of the expression as far as the > language is concerned. Whether a compiler rearranges it in > generated code in a way that is more convenient of faster or > whatever is another matter. > > I would quibble with this idea that the compiler "removes" > parentheses. I get the intuition, but C is not Go where the > compiler "inserts" semi-colons for you, and has no analogous > concept. Rather, as I think Keith said, expressions are parsed > into some internal representation, and then transformed into > something like an abstract syntax tree, where syntactic > notations like parentheses are lost. > > Both expressions above correspond to an AST like: > > ┌───────┐ > │BinOp +│ > └───────┘ > ╱ ╲ > ╱ ╲ > ┌───────┐ ┌───────┐ > │BinOp *│ │Sym `c`│ > └───────┘ └───────┘ > ╱ ╲ > ╱ ╲ > ┌───────┐ ┌───────┐ > │Sym `a`│ │Sym `b`│ > └───────┘ └───────┘ > > But the to get to that, it may be that the compiler uses a > different initial representation, like a parse tree that more > closely resembles the source language grammar. Here, the > two expressions might have different parsed representations. > E.g., for the first, simplifying heavily, may look something > like this: > > ┌──────┐ > │ expr │ > └──────┘ > ╱ │ ╲ > ╱ │ ╲ > ┌─────┐ . ┌─────┐ > │term │ (+) │term │ > └─────┘ ' └─────┘ > ╱ │ ╲ │ > ╱ │ ╲ │ > ┌─────┐ . ┌─────┐ ┌─────┐ > │ident│ (*) │ident│ │ident│ > └─────┘ ' └─────┘ └─────┘ > │ │ │ > │ │ │ > .─. .─. .─. > (`a`) (`b`) (`c`) > `─' `─' `─' > > While the second might add an extra `expr` node, as in: > > ┌──────┐ > │ expr │ > └──────┘ > ╱ │ ╲ > ╱ │ ╲ > ┌──────┐ . ┌─────┐ > │ expr │ (+) │term │ > └──────┘ ' └─────┘ > │ │ > │ │ > ┌─────┐ ┌─────┐ > │term │ │ident│ > └─────┘ └─────┘ > ╱ │ ╲ │ > ╱ │ ╲ │ > ┌─────┐ . ┌─────┐ .─. > │ident│ (*) │ident│ (`c`) > └─────┘ ' └─────┘ `─' > │ │ > │ │ > .─. .─. > (`a`) (`b`) > `─' `─' > > I believe that the answer, for most compilers that parse and > then convert to an AST, the second is more likely to be created > than the first. However, given that the same AST is created > from both parse trees, this is unlikely to have an effect on the > object code ultimately output from the compiler. You're describing a 'Concrete Syntax Tree' or CST, versus AST. Although in that case, I expect to see a discrete node for bracketed expressions (ie. parenthesised), as those would also have a distinct production in any formal grammar. Personally I don't have much use for CSTs for a normal compiler, but they might be useful for source-to-source translators, or programs that do source refactoring, where you want to preserve extras such as parentheses even if they're not strictly needed. (Injecting the right parentheses for examples like `(a + b) * c' which would have an AST like '(* (+ a b) c)' is surpringly tricky. Easier to just follow the original source! In any case, that still wouldnt't turn ((a+b)) back into the original; you'd need a suitable CST.)
[toc] | [prev] | [next] | [standalone]
| From | cross@spitfire.i.gajendra.net (Dan Cross) |
|---|---|
| Date | 2026-06-02 15:19 +0000 |
| Subject | Re: Parentheses (was: this girl calls c ugly) |
| Message-ID | <10vms98$cev$2@reader1.panix.com> |
| In reply to | #399626 |
In article <10vmmc2$2utb2$2@dont-email.me>, Bart <bc@freeuk.com> wrote: >On 02/06/2026 14:05, Dan Cross wrote: >You're describing a 'Concrete Syntax Tree' or CST, versus AST. Yes. "Concrete Syntax Tree" is another name for "Parse Tree". >Although in that case, I expect to see a discrete node for bracketed >expressions (ie. parenthesised), as those would also have a distinct >production in any formal grammar. Was that not in the second parse tree diagram I presented? Granted, I called it "expr", but as I noted, I was simplifying heavily, mostly for space. >Personally I don't have much use for CSTs for a normal compiler, but >they might be useful for source-to-source translators, or programs that >do source refactoring, where you want to preserve extras such as >parentheses even if they're not strictly needed. I think you're missing the point, here. The question was whether, given some compiler, `a*b + c` generates different code from `(a*b) + c`, and what it means for the compiler to "remove the parentheses." I submit that, with respect to the former, the answer is "very very unlikely" and with respect to the latter, the question is a category error. >(Injecting the right parentheses for examples like `(a + b) * c' which >would have an AST like '(* (+ a b) c)' is surpringly tricky. Easier to >just follow the original source! > >In any case, that still wouldnt't turn ((a+b)) back into the original; >you'd need a suitable CST.) That's not related to what I was trying to convey. - Dan C.
[toc] | [prev] | [next] | [standalone]
| From | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-06-03 22:30 +0000 |
| Subject | Re: Parentheses |
| Message-ID | <10vq9u1$2frot$1@paganini.bofh.team> |
| In reply to | #399626 |
Bart <bc@freeuk.com> wrote:
>
> Personally I don't have much use for CSTs for a normal compiler, but
> they might be useful for source-to-source translators, or programs that
> do source refactoring, where you want to preserve extras such as
> parentheses even if they're not strictly needed.
>
> (Injecting the right parentheses for examples like `(a + b) * c' which
> would have an AST like '(* (+ a b) c)' is surpringly tricky. Easier to
> just follow the original source!
You probably mean some more complicated example. This one is
easy:
(10) -> parse("(a + b) * c")
(10) (* (+ a b) c)
(11) -> unparse(parse("(a + b) * c"))
(11) "(a+b)*c"
(12) -> parse("a + b * c")
(12) (+ a (* b c))
(13) -> unparse(parse("a + b * c"))
(13) "a+b*c"
You just need to track priorities of subexpressions to produce the
above: '+' has lower priority than '*' so subexpression needs
parentheses, '*' has higher priority, so there is no need for
parentheses.
--
Waldek Hebisch
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2026-06-03 16:24 -0700 |
| Subject | Re: Parentheses |
| Message-ID | <10vqd34$1qmp$1@kst.eternal-september.org> |
| In reply to | #399665 |
antispam@fricas.org (Waldek Hebisch) writes:
> Bart <bc@freeuk.com> wrote:
>> Personally I don't have much use for CSTs for a normal compiler, but
>> they might be useful for source-to-source translators, or programs that
>> do source refactoring, where you want to preserve extras such as
>> parentheses even if they're not strictly needed.
>>
>> (Injecting the right parentheses for examples like `(a + b) * c' which
>> would have an AST like '(* (+ a b) c)' is surpringly tricky. Easier to
>> just follow the original source!
>
> You probably mean some more complicated example. This one is
> easy:
>
> (10) -> parse("(a + b) * c")
>
> (10) (* (+ a b) c)
>
> (11) -> unparse(parse("(a + b) * c"))
>
> (11) "(a+b)*c"
[snip]
What tool are you using?
[...]
--
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 | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-06-04 02:03 +0000 |
| Subject | Re: Parentheses |
| Message-ID | <10vqmeb$2lqgp$2@paganini.bofh.team> |
| In reply to | #399667 |
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
> antispam@fricas.org (Waldek Hebisch) writes:
>> Bart <bc@freeuk.com> wrote:
>>> Personally I don't have much use for CSTs for a normal compiler, but
>>> they might be useful for source-to-source translators, or programs that
>>> do source refactoring, where you want to preserve extras such as
>>> parentheses even if they're not strictly needed.
>>>
>>> (Injecting the right parentheses for examples like `(a + b) * c' which
>>> would have an AST like '(* (+ a b) c)' is surpringly tricky. Easier to
>>> just follow the original source!
>>
>> You probably mean some more complicated example. This one is
>> easy:
>>
>> (10) -> parse("(a + b) * c")
>>
>> (10) (* (+ a b) c)
>>
>> (11) -> unparse(parse("(a + b) * c"))
>>
>> (11) "(a+b)*c"
> [snip]
>
> What tool are you using?
The output if from FriCAS which is largish program which except for
containing about 50000 lines of C code have almost nothing to do with C.
'unparse' is tiny part.
Expressions have different syntax, fortunately precendence of
basic arithmetic operators is the same as in C.
--
Waldek Hebisch
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2026-06-04 01:12 +0100 |
| Subject | Re: Parentheses |
| Message-ID | <10vqftg$2d72$1@dont-email.me> |
| In reply to | #399665 |
On 03/06/2026 23:30, Waldek Hebisch wrote:
> Bart <bc@freeuk.com> wrote:
>>
>> Personally I don't have much use for CSTs for a normal compiler, but
>> they might be useful for source-to-source translators, or programs that
>> do source refactoring, where you want to preserve extras such as
>> parentheses even if they're not strictly needed.
>>
>> (Injecting the right parentheses for examples like `(a + b) * c' which
>> would have an AST like '(* (+ a b) c)' is surpringly tricky. Easier to
>> just follow the original source!
>
> You probably mean some more complicated example. This one is
> easy:
>
> (10) -> parse("(a + b) * c")
>
> (10) (* (+ a b) c)
>
> (11) -> unparse(parse("(a + b) * c"))
>
> (11) "(a+b)*c"
>
> (12) -> parse("a + b * c")
>
> (12) (+ a (* b c))
>
> (13) -> unparse(parse("a + b * c"))
>
> (13) "a+b*c"
>
>
> You just need to track priorities of subexpressions to produce the
> above: '+' has lower priority than '*' so subexpression needs
> parentheses, '*' has higher priority, so there is no need for
> parentheses.
I seem to remember one problem was with minus, for example original expr is:
a - (b - c)
The AST is (- a (- b c)), but a simplistic approach would generate, from
either that or (- (- a b) c), the same output:
a - b - c
No parentheses because the the two "-" have the same precedence. The
example might have been 'a + (b - c)'; same thing.
It just seemed more trouble than it was worth.
[toc] | [prev] | [next] | [standalone]
Page 5 of 13 — ← Prev page 1 … 3 4 [5] 6 7 … 13 Next page →
Back to top | Article view | comp.lang.c
csiph-web