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 275 — 21 participants |
Back to article view | Back to comp.lang.c
this girl calls c ugly fir <profesor.fir@gmail.com> - 2026-05-27 19:53 +0200
Re: this girl calls c ugly fir <profesor.fir@gmail.com> - 2026-05-27 20:15 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-27 18:49 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 04:53 +0000
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 02:35 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 23:32 +0000
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 20:07 -0500
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-28 11:48 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-28 09:18 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 04:57 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 23:35 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 09:52 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-29 05:20 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-29 13:22 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-29 15:16 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-30 13:52 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-30 14:40 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-30 16:36 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-30 15:48 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 11:14 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-31 13:25 -0500
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 22:14 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 15:22 +0200
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-30 03:49 +0000
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-05-28 12:47 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 09:56 +0200
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-05-29 11:00 -0700
Re: this girl calls c ugly fir <profesor.fir@gmail.com> - 2026-05-28 17:12 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-28 14:07 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-28 23:54 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 10:02 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 12:19 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 14:46 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 14:22 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 17:15 +0200
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-05-29 15:59 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 17:12 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 18:48 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 19:09 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:00 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 22:14 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 12:09 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 17:05 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 18:34 +0200
Re: this girl calls c ugly tTh <tth@none.invalid> - 2026-05-29 19:29 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 18:53 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 12:28 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 20:49 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:03 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 13:56 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 22:54 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 15:52 -0700
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-29 20:31 -0400
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 02:03 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-29 19:02 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 12:12 +0100
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-05-30 12:29 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 13:56 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-30 16:43 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-31 03:37 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-30 19:53 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 12:16 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 11:47 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 12:55 +0200
Re: this girl calls c ugly Richard Harnden <richard.nospam@gmail.invalid> - 2026-05-31 09:12 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 11:49 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-31 11:10 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 13:18 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 10:24 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 17:35 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 12:46 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 22:24 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 18:26 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 08:28 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 15:54 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 08:39 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 02:33 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 11:48 +0200
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-02 06:37 -0400
Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-02 05:06 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 16:28 +0000
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 03:37 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 16:31 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 13:36 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 23:49 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 18:04 -0700
Re: Constants and undefined behavior cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:10 +0000
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 23:50 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 15:47 -0700
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-06 16:36 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 16:43 -0700
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-06 17:41 -0700
Re: Constants and undefined behavior Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-05 10:41 +0200
Re: Constants and undefined behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 10:49 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 16:15 -0700
Re: Constants and undefined behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-06 18:06 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 05:35 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-02 06:29 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 16:10 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 15:29 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 06:41 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 11:24 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:22 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 23:56 -0700
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-02 13:59 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 13:05 +0000
Parentheses (was: this girl calls c ugly) Bart <bc@freeuk.com> - 2026-06-02 14:38 +0100
Re: Parentheses (was: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 15:19 +0000
Re: Parentheses antispam@fricas.org (Waldek Hebisch) - 2026-06-03 22:30 +0000
Re: Parentheses Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-03 16:24 -0700
Re: Parentheses antispam@fricas.org (Waldek Hebisch) - 2026-06-04 02:03 +0000
Re: Parentheses Bart <bc@freeuk.com> - 2026-06-04 01:12 +0100
Re: Parentheses antispam@fricas.org (Waldek Hebisch) - 2026-06-04 01:58 +0000
Re: Parentheses Bart <bc@freeuk.com> - 2026-06-04 11:37 +0100
Re: Parentheses cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 10:51 +0000
Re: Parentheses Bart <bc@freeuk.com> - 2026-06-04 12:47 +0100
Re: Parentheses Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 14:57 +0200
Re: Parentheses cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 14:31 +0000
[OT] Fancy graphics (was Re: this girl calls c ugly) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 15:54 +0200
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Bart <bc@freeuk.com> - 2026-06-02 15:19 +0100
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 15:19 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 17:39 +0200
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 16:36 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) scott@slp53.sl.home (Scott Lurndal) - 2026-06-02 21:33 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-02 14:43 -0700
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) ram@zedat.fu-berlin.de (Stefan Ram) - 2026-06-02 17:08 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 19:19 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-04 00:11 +0000
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 15:39 -0700
Re: [OT] Fancy graphics (was Re: this girl calls c ugly) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-03 13:14 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-02 15:10 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 15:31 +0000
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-31 10:15 -0400
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 16:29 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 03:45 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 04:02 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 09:04 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-31 18:11 +0100
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-05-31 19:34 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 19:10 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 11:12 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 12:36 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 14:26 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 02:34 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 12:40 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 14:35 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 14:18 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 15:47 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 15:57 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 16:27 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 16:46 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 20:15 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 20:54 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 20:29 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 14:06 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 22:47 +0100
Famous (hopefully last) words [on this topic] Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-05 00:27 +0200
Re: Famous (hopefully last) words [on this topic] Bad Post <invalid@invalid.invalid> - 2026-06-05 01:20 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 16:09 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 00:44 +0100
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-04 17:26 -0700
Re: this girl calls c ugly antispam@fricas.org (Waldek Hebisch) - 2026-06-05 12:58 +0000
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-05 14:27 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 02:47 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 00:53 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 11:04 +0100
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 05:34 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:45 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:44 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-06 07:39 +0200
Re: this girl calls c ugly "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-06-04 15:25 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-05 09:29 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 12:39 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-05 15:42 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 16:50 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 11:09 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-05 20:29 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 16:18 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 17:23 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 16:47 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 19:57 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 20:34 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-04 22:28 +0100
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 21:58 +0000
Re: this girl calls c ugly Richard Harnden <richard.nospam@gmail.invalid> - 2026-06-04 23:25 +0100
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 02:49 +0000
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 19:47 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-04 21:04 +0200
Re: this girl calls c ugly Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2026-06-04 19:13 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-05 10:34 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 12:11 -0700
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-06-04 16:33 -0400
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 14:16 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 00:02 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 18:36 -0700
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 02:54 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 05:49 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-05 11:01 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-05 11:53 -0700
Re: this girl calls c ugly Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2026-06-04 18:45 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 20:19 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 20:31 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-04 20:41 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-04 20:49 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 00:03 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-05 00:18 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-05 03:02 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-05 14:04 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-06 03:49 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-06 15:13 +0000
Re: this girl calls c ugly scott@slp53.sl.home (Scott Lurndal) - 2026-06-06 17:53 +0000
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-04 11:59 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-04 15:21 +0200
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 06:38 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 09:52 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 02:42 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 12:50 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 11:47 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 12:55 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 14:39 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 15:11 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 08:41 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 02:07 -0700
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 11:38 +0200
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 05:01 -0700
It is not futile to change the subject line (Was: this girl calls c ugly) gazelle@shell.xmission.com (Kenny McCormack) - 2026-06-02 12:39 +0000
Re: It is not futile to change the subject line (Was: this girl calls c ugly) gazelle@shell.xmission.com (Kenny McCormack) - 2026-06-02 12:42 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 11:46 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-02 11:09 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 05:25 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-02 14:20 +0100
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-02 15:12 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-02 04:16 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-01 15:23 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-06-01 16:06 -0700
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 23:24 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-06-02 11:35 +0200
Operator precedence in other (non-C, but "C-like") languages (Was: something about a girl) gazelle@shell.xmission.com (Kenny McCormack) - 2026-06-02 12:36 +0000
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-01 11:04 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-01 14:04 +0200
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-01 18:48 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 21:04 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 09:17 +0200
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 09:09 +0200
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-06-02 12:07 +0000
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-06-02 14:37 +0200
Microcontroller software stacks (was Re: this girl calls c ugly) scott@slp53.sl.home (Scott Lurndal) - 2026-06-02 15:06 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-06-04 03:58 -0700
Re: this girl calls c ugly dave_thompson_2@comcast.net - 2026-06-06 19:02 -0400
Re: this girl calls c ugly cross@spitfire.i.gajendra.net (Dan Cross) - 2026-05-31 19:11 +0000
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 16:08 -0700
Re: this girl calls c ugly Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-05-31 16:32 -0700
Re: this girl calls c ugly Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-05-31 17:12 -0700
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-30 14:07 +0200
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 18:10 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 19:18 +0100
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:17 +0200
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-29 21:47 +0100
Re: this girl calls c ugly James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-05-29 15:57 -0400
Re: this girl calls c ugly Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2026-05-29 22:34 +0200
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-29 23:18 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 01:26 +0100
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-30 04:25 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-30 12:01 +0100
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-31 00:29 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-05-31 10:59 +0100
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-06-01 00:33 +0000
Re: this girl calls c ugly Bart <bc@freeuk.com> - 2026-06-01 02:26 +0100
Re: this girl calls c ugly David Brown <david.brown@hesbynett.no> - 2026-05-31 13:24 +0200
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-29 08:09 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-29 04:15 -0500
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-29 14:58 +0200
Re: this girl calls c ugly BGB <cr88192@gmail.com> - 2026-05-30 01:04 -0500
Re: this girl calls c ugly Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-29 23:20 +0000
Re: this girl calls c ugly Bonita Montero <Bonita.Montero@gmail.com> - 2026-05-30 11:18 +0200
Page 1 of 14 [1] 2 3 … 14 Next page →
| From | fir <profesor.fir@gmail.com> |
|---|---|
| Date | 2026-05-27 19:53 +0200 |
| Subject | this girl calls c ugly |
| Message-ID | <10v7b32$2u85v$1@dont-email.me> |
https://www.youtube.com/watch?v=I7fEsbksKRE as far as i understood..(becouse if someona talks english fast my mind tend to skip more than half of the message) overally this is quite curious... she probably read this articles etc for lisp ponys who say lisp is beautifull and c is not so much... but still this is much of incompetence call c ugly...
[toc] | [next] | [standalone]
| From | fir <profesor.fir@gmail.com> |
|---|---|
| Date | 2026-05-27 20:15 +0200 |
| Message-ID | <10v7cc9$2ul59$1@dont-email.me> |
| In reply to | #399456 |
fir pisze: > https://www.youtube.com/watch?v=I7fEsbksKRE > > as far as i understood..(becouse if someona talks english fast my mind > tend to skip more than half of the message) > > overally this is quite curious... > > > she probably read this articles etc for lisp ponys who say lisp is > beautifull and c is not so much... but still this is much of > incompetence call c ugly... > well i see she named bjorne stroustrup smart (well i wouldnt be so bold here) - and said he took UGLY c and combined it with OO so this make a c++ 'succesfull' language which takes much hate so i understand c is ugly and to blame c++ is hated... instead of coding in lisp... now thats where comedy possibly gets too strong :3 (now im quite convinced my comment on this is also not too strong in bad way of its sense but i was kinda really stunned/surprised ehen someona talks such things on video ) -,-
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-27 18:49 -0500 |
| Message-ID | <10v7vuo$33u4c$1@dont-email.me> |
| In reply to | #399457 |
On 5/27/2026 1:15 PM, fir wrote:
> fir pisze:
>> https://www.youtube.com/watch?v=I7fEsbksKRE
>>
>> as far as i understood..(becouse if someona talks english fast my mind
>> tend to skip more than half of the message)
>>
>> overally this is quite curious...
>>
>>
>> she probably read this articles etc for lisp ponys who say lisp is
>> beautifull and c is not so much... but still this is much of
>> incompetence call c ugly...
>>
>
> well i see she named bjorne stroustrup smart (well i wouldnt be so bold
> here) - and said he took UGLY c and combined it with OO so this make a
> c++ 'succesfull' language which
> takes much hate
>
> so i understand c is ugly and to blame c++ is hated... instead of coding
> in lisp... now thats where comedy possibly gets too strong :3
>
> (now im quite convinced my comment on this is also not too strong in bad
> way of its sense but i was kinda really stunned/surprised ehen someona
> talks such things on video ) -,-
In general I like her videos, and she seems to know what she is talking
about...
But, I am not personally as much of a fan of C++ as she is...
Like, say:
Early days (once when I was still young):
Main compiler I used was Cygwin, but "g++" tended not to work.
Like, at the time, had the ever-present GCC 2.95.2, ...
Any attempt to compile C++ resulted in a mess of error messages.
Later:
I experimented with it, but:
It didn't do that much that wasn't syntactic sugar over C.
I was using customized tools that worked OK with C,
but C++ made many headaches with inter-op with custom tools.
If you have C++, but can't really use any features without issues,
it kinda defeats the point vs just using C.
Later still:
My custom compiler can't use more than a 90s era subset;
So, to really make use of any newer/fancier features,
I would greatly limit where I could use the code.
People can be like:
"But, Templates, and STL containers..."
And I can be like:
"But then your binaries are huge and build times suck..."
Similar reason to why one doesn't build complex patterns or do
template-like stuff via function macros in the C preprocessor:
One can do this... But again, bloated binaries and terrible build times.
So, one is back to the core issue:
The part that is actually usable, mostly still amounts to syntactic
sugar over things you can already do in C.
There are "niceties", granted, but relatively little "actually new".
And, one of the rare few "actually new" features C++ offers: exceptions.
Also comes with its own drawbacks (code bloat, try/catch+throw is
usually slow, use with care else program explodes, ...). Unlike many
other features, C++ exceptions are also ones that add a (small but often
non-zero) code-bloat and performance penalty to pretty much *every*
function, regardless of whether or not they actually use exceptions
(because, they could potentially call something, somewhere, that uses
exceptions, and so the compiler needs to provide for the possibility
that an exception could come through this section of code).
Many people coding styles often forbid it and mandate that people use
error-code returns or similar instead (like in C), with exceptions being
globally disabled at build time (along with RTTI and similar), which,
isn't really a strong selling point...
And, many examples we have of non-trivial projects using C++, such as
LLVM/Clang, also tend to own pretty much any computer that one dares use
to try to compile it...
Or, Doom3, which isn't *that* much bigger than Quake 3 code wise, and
still uses a mostly C like subset of C++, but for whatever unexplained
reason, seems to take an order of magnitude longer to recompile from
source (... over 10 minutes ...).
...
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-05-28 04:53 +0000 |
| Message-ID | <10v8hot$37ld2$2@dont-email.me> |
| In reply to | #399461 |
On Wed, 27 May 2026 18:49:38 -0500, BGB wrote: > But, I am not personally as much of a fan of C++ as she is... C++ syntax is so complex, the language spec has to add rules that say, in case of ambiguity, that this interpretation is meant and not that. Someone described this as “the principle of most surprise”.
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-28 02:35 -0500 |
| Message-ID | <10v8r8d$39ut3$1@dont-email.me> |
| In reply to | #399466 |
On 5/27/2026 11:53 PM, Lawrence D’Oliveiro wrote:
> On Wed, 27 May 2026 18:49:38 -0500, BGB wrote:
>
>> But, I am not personally as much of a fan of C++ as she is...
>
> C++ syntax is so complex, the language spec has to add rules that say,
> in case of ambiguity, that this interpretation is meant and not that.
>
> Someone described this as “the principle of most surprise”.
Someone could almost come up with a language that is "like C++ but less
horrible".
Core language:
Like a C / C# hybrid;
Base language could superficially resemble C++;
In any case, avoid needlessly changing basic syntax.
Designed to be easier to write a compiler;
Designed so that compiler isn't dead slow;
Goal should be that compiled code performance remain similar to C;
Shouldn't do things that would exclude it from C like use cases.
Type-system and memory model is mostly similar to C.
Could impose that declaration types work more like in C#;
SI + Interfaces rather than full MI;
Generic Types rather than Templates;
...
Parsing would follow a "can it reasonably be parsed as X" approach:
If something can syntactically be parsed as a cast/etc, assume it is so;
If this assumption turns out to be wrong, compiler error.
In this case, assume that types/etc may only appear in certain contexts,
and can apply on "<type_expr> <identifier>" pattern recognition to
detect declarations. Trying to put a declaration (or generic invocation)
somewhere where it doesn't normally go, being a syntax error.
Say:
if(int i=0)
{ ... }
Would be regarded as illegal (but could be allowed as a special case in
"for()" loops due to popularity).
Core type-system is C like:
Type consists of a base-type and any modifiers;
Base type names:
char, byte, short, int, long, float, double, ...
Type Modifiers:
signed, unsigned, const, volatile, ...
Where, const and volatile behave like in C.
Base type sizes (bits):
char 8 //ASCII / UTF-8
wchar 16 //UCS-2 / UTF-16
lchar 32 //UCS-4 / UTF-32
byte 8
sbyte 8
ubyte 8
short 16
int 32
long 64
float 32
double 64
Issue:
Would want to disallow compound type names, like "long long" or "long
double".
As soon as the syntax allows this, an ambiguity is created that
adversely effects parser speed.
One other option could be to provide a set of explicit sized types:
int8, int16, int32, int64, int128
uint8, uint16, uint32, uint64, uint128
float16, float32, float64, float128
...
In terms of representation, byte and char would be equivalent, except
that it might make sense to treat 'char' as not normally an arithmetic
type, so in order to perform arithmetic on char it would be cast to
'int' or similar.
Could assume that a "string" type exists, but primarily exists as an
opaque "const char *" pointer.
Nominally, string literals could be stored prefixed with a length stored
as a transposed UTF-8 codepoint (along with also having a NUL
terminator). But, unlike "const char *", "string" would not allow
pointer arithmetic, and so would always point to the start of the string
literal, or to an explicitly interned string (doing otherwise would be
erroneous).
While it is "trendy" in some languages to treat "string" as some sort of
object type, actually doing string as an object is needlessly wasteful.
Likewise, storing a length as a prefix still allows "string.length" or
similar to be O(1). Could assume default string format is UTF-8, but
mostly treated as a blob of bytes.
While some languages (Java and C#) went over to UTF-16, this is
needlessly wasteful of memory and breaks with C tradition.
Likely memory management:
Generic heap, new/delete;
No GC, as IMO no one thus far has made GC work sufficiently well.
Zones / arenas;
Initially resembles heap allocs,
but all objects in a zone can be bulk freed;
Some objects could be set to track their self-pointer;
Self-pointer is NULL'ed if object is freed.
Essentially, similar to Doom's Z_Malloc.
Automatic:
Freed by default as soon as parent frame exits.
OO:
Likely treat 'class' and 'struct' as distinct.
Objects are reference type by default (like in C#/Java);
However, will typically still have automatic lifetime if local.
Could likely still have RAII, but may manifest differently.
Structs would behave like C structs or C++ by_value classes.
Will explicitly forbid inheritance or virtual methods.
Could maybe have copy-constructors and destructors.
More likely to be used for C++ style RAII patterns.
The more restrictive object model would avoid a "big chunk of evil" that
exists if trying to write a C++ compiler. Elimination of full MI
eliminates a lot of complexity; as does eliminating inheritance on
by-value types.
Declaration imports:
Would likely make sense to replace the reliance on "#include" with
something more resembling the "import" mechanism from Java;
Though would differ in that the imports identify source files rather
than classes;
Would likely treat package/import scope, name namespace scope, as two
different entities. The package/import would resemble the mechanism in
Java, but would instead merely import things at toplevel scope, and
within an imported module.
Namespace would be used in a way more like that of C++ or C# namespaces:
namespace whatever { using whatever_else; ... }
It is likely that compiler would first generate a "declaration manifest"
which would be used for these purposes.
Compiling Foo:
import bar;
Checks if bar has a manifest;
If yes:
Import manifest for bar;
Add 'bar' to object dependency graph;
Also import any of bar's dependencies.
If no:
Trigger frontend only compilation for 'bar';
If success:
Import manifest for bar;
Add 'bar' to object dependency graph;
Else:
Compiler error.
Compiler would likely deal with dependency compilation as a sort of
stack machine, where imports are dealt with before compiling the main
body of each module. This being to avoid excessive recursion and memory
usage during dependency importing.
Would likely make sense to keep a C style preprocessor, but using it for
headers could be discouraged (this being a great source of compile-time
inefficiency in both C and C++).
...
Well, wont amount to much, just idle thoughts...
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-05-28 23:32 +0000 |
| Message-ID | <10vaj9v$3phl1$7@dont-email.me> |
| In reply to | #399470 |
On Thu, 28 May 2026 02:35:37 -0500, BGB wrote: > Someone could almost come up with a language that is "like C++ but less > horrible". Like this? <https://en.wikipedia.org/wiki/Carbon_(programming_language)>
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-28 20:07 -0500 |
| Message-ID | <10vaos1$3r7bg$1@dont-email.me> |
| In reply to | #399479 |
On 5/28/2026 6:32 PM, Lawrence D’Oliveiro wrote:
> On Thu, 28 May 2026 02:35:37 -0500, BGB wrote:
>
>> Someone could almost come up with a language that is "like C++ but less
>> horrible".
>
> Like this? <https://en.wikipedia.org/wiki/Carbon_(programming_language)>
Well, except that the language I am imagining would probably still look
more C-like (where, say, C-like core but borrowing some things from C#
and Java rather than aiming to to be like C++; but in terms of
implementation and ABI would be sorta like C++).
Possibly something like:
import C.stdio;
int main(int argc, const char **argv)
{
printf("hello world, called as %s\n", argv[0]);
return(0);
}
Where, say, new language inherits the C standard library, just using
import rather than #include .
Then, say, if we wanted a 2D vector type, say:
namespace foo {
struct Vector2D {
double x;
double y;
Vector2D(double ax, double ay)
{ x=ax; y=ay; }
}
Vector2D operator+(Vector2D a, Vector2D b)
{
return (Vector2D) { .x=a.x+b.x, .y=a.y+b.y };
}
double operator^(Vector2D a, Vector2D b)
{
return a.x*b.x + a*y+b.y;
}
}
Then, say:
using foo; //can skip 'namespace' keyword, as redundant here.
Vector2D test1()
{
Vector2D v0(1.0, 2.0);
Vector2D v1(3.0, 4.0);
Vector2D v2 = v0 + v1;
return v2;
}
Or, for a class type:
public class Foo {
double x, y;
Foo(double ax, double ay)
{ x=ax; y=ay; }
}
public interface IBaz {
//public and virtual by default
double get_x();
double get_y();
void set_x(double val);
void set_y(double val);
}
public class Bar:Foo,IBaz {
//public virtual via IBaz
double get_x() { return x; }
double get_y() { return y; }
void set_x(double val) { x=val; }
void set_y(double val) { y=val; }
}
...
{
IBaz obj1 = new Bar(1.0, 2.0);
}
And, if generics exist, say:
struct GenericVec2D<T> {
T x;
T y;
...
}
GenericVec2D<float> v2f0;
This instantiates a new type, say:
GenericVec2D$float
Where all instances of type 'T' become 'float'.
So, more in the vain of C mixed with C# and Java, not like some language
that diverges more drastically from C family conventions...
Where, like C# (and unlike C++), classes are always by-reference, and
structs always by value, and structs will forbid inheritance, ...
Could maybe also define that any functions declared at the global
top-level have C like binding, with name-mangling and overloading only
applying within namespaces or within struct/class methods.
Note that SI+interfaces would effectively eliminate things like diamond
inheritance and virtual inheritance (in effect, class layout will be
append-only).
In-memory layout for classes could be sort of like:
vtable_pointer (shared across all classes)
data for parent class
interface vtable pointer(s) for parent class
-- end of parent class --
data for child class
interface vtable pointer(s) for child class
only for newly-implemented interfaces.
-- end of child class --
Each interface VTable could have a layout like, say:
Index 0: ClassInfo / RTTI
Index 1: Offset from Interface Vtable pointer to Base-Class.
Index 2: First Method
Index 3: Second Method
...
For base classes, it is nearly identical, except that offset is always 0.
...
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2026-05-28 11:48 +0200 |
| Message-ID | <10v9313$3bub1$1@raubtier-asyl.eternal-september.org> |
| In reply to | #399466 |
Am 28.05.2026 um 06:53 schrieb Lawrence D’Oliveiro: > C++ syntax is so complex, the language spec has to add rules that say, > in case of ambiguity, that this interpretation is meant and not that. There only a few amiguities, mainly the most vexing parse.
[toc] | [prev] | [next] | [standalone]
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-05-28 09:18 +0200 |
| Message-ID | <10v8q7n$2a26g$1@dont-email.me> |
| In reply to | #399461 |
On 2026-05-28 01:49, BGB wrote: >> [...] > > In general I like her videos, and she seems to know what she is talking > about... > > But, I am not personally as much of a fan of C++ as she is... I'm a big fan of abstractions. - So many things beyond "C" are fine! > [...] > > [ Cygwin ] A sensible but imperfect workaround provided for an inferior platform. > [...] > > Similar reason to why one doesn't build complex patterns or do template- > like stuff via function macros in the C preprocessor: > One can do this... But again, bloated binaries and terrible build times. Code patterns that are bulky in "C" can be formulated tersely with C++/STL (while still preserving an efficient implementation, even with complexities guaranteed); and the framework is flexible, orthogonally designed. Easy to reuse high-level concepts as opposed to re-implement the same code for different types. Or weaken the code by extensive use of casts. All sorts of C's problems with memory can be addressed. (The list can be continued; but I wonder why such things aren't recognized.) > > So, one is back to the core issue: > The part that is actually usable, mostly still amounts to syntactic > sugar over things you can already do in C. Huh? It may depend on the developer/programmer. But it's certainly a lot more than "syntactic sugar". > > There are "niceties", granted, but relatively little "actually new". Not all concepts are "new", of course; we saw them in other languages years or (in some cases) decades ago. But C++' and STL features are a lot more than just niceties; it's beyond me how one may come to such a valuation. (And now let's compare that formulated demand or wish of new things with "C"?) > > And, one of the rare few "actually new" features C++ offers: exceptions. We used them already in the 1990's. > Also comes with its own drawbacks (code bloat, try/catch+throw is > usually slow, use with care else program explodes, ...). [...] I cannot confirm your statements, especially in that generality. I recall we had bloat with templates on a specific platform in the very early pre-standard era, when they were first supported. But we didn't have any [noteworthy] speed degradation with exceptions (or templates). > > Many people coding styles often forbid it and mandate that people use > error-code returns or similar instead (like in C), with exceptions being > globally disabled at build time (along with RTTI and similar), which, > isn't really a strong selling point... Yes, stupid things are done. Mandating to use RCs and forbid to use exceptions is particularly stupid as a general rule. Probably mentally inconvenient as "new" concept for FORTRAN, BASIC, or "C" programmers? I can certainly understand that, psychologically. But not technically. Maybe the support on the commercial platforms was just better than on Cygwin? Janis > [...]
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-28 04:57 -0500 |
| Message-ID | <10v93ia$3bu3a$1@dont-email.me> |
| In reply to | #399469 |
On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
> On 2026-05-28 01:49, BGB wrote:
>>> [...]
>>
>> In general I like her videos, and she seems to know what she is
>> talking about...
>>
>> But, I am not personally as much of a fan of C++ as she is...
>
> I'm a big fan of abstractions. - So many things beyond "C" are fine!
>
I am not saying that abstractions are bad, but I haven't usually found
them to be worth the costs IME.
>> [...]
>>
>> [ Cygwin ]
>
> A sensible but imperfect workaround provided for an inferior platform.
>
Yeah.
It was the main thing I had when I was in high-school.
Well, Cygwin and MinGW.
By college, the "Windows Platform SDK" became freely available, and I
mostly ended up jumping over this for native Windows development.
At least the C++ compiler worked, still failed to fully win me over.
Tried writing minor things in C++, mixed results.
>> [...]
>>
>> Similar reason to why one doesn't build complex patterns or do
>> template- like stuff via function macros in the C preprocessor:
>> One can do this... But again, bloated binaries and terrible build times.
>
> Code patterns that are bulky in "C" can be formulated tersely with
> C++/STL (while still preserving an efficient implementation, even with
> complexities guaranteed); and the framework is flexible, orthogonally
> designed. Easy to reuse high-level concepts as opposed to re-implement
> the same code for different types. Or weaken the code by extensive use
> of casts. All sorts of C's problems with memory can be addressed. (The
> list can be continued; but I wonder why such things aren't recognized.)
>
Both have a similar issue when used in a naive way though:
Non-careful use of either results in code bloat.
But, not really an "easy" way to avoid bloat, other than to write code
specifically for what cases are relevant; while also avoiding needless
duplication and copy paste (where, overuse of copy/paste can also lead
to bloat; along with turning the code into an ugly mess).
But, OTOH, factoring things into too small of pieces can negatively
effect performance (and, for non-leaf functions, prolog/epilog costs for
too many tiny functions can also be a source of code bloat).
As can be noted, trying to mimic templates via creative use of C
preprocessor macros can also easily result in excessive bloat...
>>
>> So, one is back to the core issue:
>> The part that is actually usable, mostly still amounts to syntactic
>> sugar over things you can already do in C.
>
> Huh? It may depend on the developer/programmer. But it's certainly a
> lot more than "syntactic sugar".
>
Well, for example:
Operator overloading:
Basically glorified function calls made to resemble operators;
Classes:
Can be done with structs, and implementing vtables manually.
Implementing class hierarchies via structs can be done, but gets ugly
(GTK's GObject system sorta went this way).
...
>>
>> There are "niceties", granted, but relatively little "actually new".
>
> Not all concepts are "new", of course; we saw them in other languages
> years or (in some cases) decades ago. But C++' and STL features are a
> lot more than just niceties; it's beyond me how one may come to such
> a valuation. (And now let's compare that formulated demand or wish of
> new things with "C"?)
>
Well, it is a thing that can be done, but is a double-edged sword.
Saves code one might have to write out manually.
But, is very easy to result in things that negatively effect build times.
Usual strategy is to try to limit how much code is written, and also to
avoid doing things in ways that result in too much code, or too much cruft.
Best to avoid both copy paste when reasonable, and sticking anything
non-trivial in macros.
>>
>> And, one of the rare few "actually new" features C++ offers: exceptions.
>
> We used them already in the 1990's.
>
Here, "new" in the sense that it can't be mapped directly back to stuff
that can already be expressed natively in C.
>> Also comes with its own drawbacks (code bloat, try/catch+throw is
>> usually slow, use with care else program explodes, ...). [...]
>
> I cannot confirm your statements, especially in that generality.
>
> I recall we had bloat with templates on a specific platform in the
> very early pre-standard era, when they were first supported. But we
> didn't have any [noteworthy] speed degradation with exceptions (or
> templates).
>
The relative impact of try/catch is more modest.
Typically, it results in every function having an unwind-handling stub
for, in-case an exception is thrown, it can call any destructors or similar.
This will depend a lot of the target and ABI, but for example, in my
compiler, having exceptions enabled ends up costing around an extra 48
bytes for every non-leaf function.
This can easily add up to a fair number of kB over the size of a program
binary even if they aren't used.
The per-function cost would be higher for functions which have objects
with destructors or catch handlers. One could easily be looking at 100s
of additional bytes for each such function.
>>
>> Many people coding styles often forbid it and mandate that people use
>> error-code returns or similar instead (like in C), with exceptions
>> being globally disabled at build time (along with RTTI and similar),
>> which, isn't really a strong selling point...
>
> Yes, stupid things are done. Mandating to use RCs and forbid to use
> exceptions is particularly stupid as a general rule.
>
> Probably mentally inconvenient as "new" concept for FORTRAN, BASIC,
> or "C" programmers? I can certainly understand that, psychologically.
> But not technically. Maybe the support on the commercial platforms
> was just better than on Cygwin?
>
On Cygwin, in the early 2000s, "g++" tended to often not work at all...
MSVC gave a better experience in that at least the compiler worked.
Now, as for the rules like this in many coding standards, can't speak
for all of them.
But, the main thing that stands out to me is how many of the projects
that use C++ have absurdly slow build times and huge binaries.
Like, someone is like, "Thing takes 10 minutes to compile and the EXE is
50MB? Seems fine to me..."
Well, or LLVM, which can take upwards of an hour to rebuild from source,
and eats huge amounts of RAM and HDD space while doing so.
So, yeah, I don't really use LLVM...
My own C compiler rebuilds from source in around 20 seconds or so.
Well, or 1m38s via GCC...
But, yeah however long is considered a reasonable amount of time to
recompile a 370 kLOC C compiler...
MSVC produces an 5.5MB EXE, whereas GCC produces a 12MB ELF.
If I switch "-O3" to "-Os":
Time drops to 0m58s.
ELF goes to 7MB.
Still pretty big...
Granted, my C compiler's codebase is a little bigger than I would
prefer, but alas...
Granted, my C compiler isn't itself all that fast at compiling stuff, sadly:
It also takes around 20 seconds to recompile Doom (vs around 5 seconds
for MSVC).
And, GCC takes around 16 seconds to recompile Doom.
So, yeah, as for its compiling-stuff speeds, it is typically slower than
GCC.
Doom sizes:
MSVC : 776K (x64)
GCC : 500K (x86-64)
GCC : 1.2MB (RV64G, ELF)
BGBCC : 272K (XG3, *)
*: Custom ISA stuff bolted onto RISC-V (with 32/64/96 bit instructions,
goes to bigger instructions rather than smaller, and expands register
fields to 6-bits using both X and F registers as GPRs, so is the
opposite of RV-C in this sense; but manages to compete for code density
by reducing overall instruction counts).
For binary sizes, it is pretty close between XG3 and a
differently-extended version of RV64GC though. Not yet a clear winner of
the code-density crown, but it does more solidly win on speed.
Where, XG3 was more meant for optimizing the design for speed, but to
some extent optimizing the design for speed also helps with code density.
Though, for RV64G, GCC seems to produce a lot of bloat in the ELF
binaries through the use of excessive amounts of metadata, which is
already fairly bulky in the ELF format if contrast with PE/COFF (which
is what my compiler generates).
...
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <ldo@nz.invalid> |
|---|---|
| Date | 2026-05-28 23:35 +0000 |
| Message-ID | <10vajfd$3phl1$8@dont-email.me> |
| In reply to | #399472 |
On Thu, 28 May 2026 04:57:18 -0500, BGB wrote: > It was the main thing I had when I was in high-school. Well, Cygwin > and MinGW. Did you ever discover the platform that they were trying to emulate?
[toc] | [prev] | [next] | [standalone]
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-05-29 09:52 +0200 |
| Message-ID | <10vbgkc$3uus7$1@dont-email.me> |
| In reply to | #399472 |
On 2026-05-28 11:57, BGB wrote:
> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>> On 2026-05-28 01:49, BGB wrote:
[...]
>> I'm a big fan of abstractions. - So many things beyond "C" are fine!
>
> I am not saying that abstractions are bad, but I haven't usually found
> them to be worth the costs IME.
Wow! - That's completely different from my experience and practice.
It's what makes usage simple, fast, reliable. Not wasting time for
details, or fixing technical bugs that should be prevented by the
language.
>
>>> [...]
>>>
>>> Similar reason to why one doesn't build complex patterns or do
>>> template- like stuff via function macros in the C preprocessor:
>>> One can do this... But again, bloated binaries and terrible build times.
>>
>> Code patterns that are bulky in "C" can be formulated tersely with
>> C++/STL (while still preserving an efficient implementation, even with
>> complexities guaranteed); and the framework is flexible, orthogonally
>> designed. Easy to reuse high-level concepts as opposed to re-implement
>> the same code for different types. Or weaken the code by extensive use
>> of casts. All sorts of C's problems with memory can be addressed. (The
>> list can be continued; but I wonder why such things aren't recognized.)
>
> Both have a similar issue when used in a naive way though:
> Non-careful use of either results in code bloat.
Okay, "when used in a in a naive way". - Let's leave it at that,
then.
>
> But, not really an "easy" way to avoid bloat, other than to write code
> specifically for what cases are relevant; while also avoiding needless
> duplication and copy paste (where, overuse of copy/paste can also lead
> to bloat; along with turning the code into an ugly mess).
Hmm.. - as said, the during very early days there were issues; I
recall on one platform duplication of template code in more that
one source unit. And/or some environmental hacks (of the compiler)
to deposit template code for linking. In the later days I've not
seen such immature things anymore.
>
> But, OTOH, factoring things into too small of pieces can negatively
> effect performance (and, for non-leaf functions, prolog/epilog costs for
> too many tiny functions can also be a source of code bloat).
>
> As can be noted, trying to mimic templates via creative use of C
> preprocessor macros can also easily result in excessive bloat...
>
>>>
>>> So, one is back to the core issue:
>>> The part that is actually usable, mostly still amounts to syntactic
>>> sugar over things you can already do in C.
>>
>> Huh? It may depend on the developer/programmer. But it's certainly a
>> lot more than "syntactic sugar".
>
> Well, for example:
> Operator overloading:
> Basically glorified function calls made to resemble operators;
> Classes:
> Can be done with structs, and implementing vtables manually.
>
> Implementing class hierarchies via structs can be done, but gets ugly
> (GTK's GObject system sorta went this way).
We obviously disagree completely in what's "syntactic sugar".
(With that reasoning all ("C" or other languages') features are
"syntactic sugar" because you can do that also with assembly?)
>>>
>>> There are "niceties", granted, but relatively little "actually new".
>>
>> Not all concepts are "new", of course; we saw them in other languages
>> years or (in some cases) decades ago. But C++' and STL features are a
>> lot more than just niceties; it's beyond me how one may come to such
>> a valuation. (And now let's compare that formulated demand or wish of
>> new things with "C"?)
>
> Well, it is a thing that can be done, but is a double-edged sword.
> Saves code one might have to write out manually.
> But, is very easy to result in things that negatively effect build times.
A simple, less-abstracted language can certainly be easier (thus
faster) translated to machine code.
I don't know about your working contexts. In our contexts slightly
larger built-times were no issue. For one, we built using makefiles,
and only full builds (to create QA test images, or public releases)
required much time; they typically ran over night; our systems were
typically very large!
Build times were also influenced by other more significant factors.
Mundane sounding things like ordering of functions in libraries and
some such. (Though nothing that wouldn't have been possible to be
addressed by the build-management group.)
>
> Usual strategy is to try to limit how much code is written, and also to
> avoid doing things in ways that result in too much code, or too much cruft.
>
> Best to avoid both copy paste when reasonable, and sticking anything
> non-trivial in macros.
We avoided macros if possible.
>
>>> And, one of the rare few "actually new" features C++ offers: exceptions.
>>
>> We used them already in the 1990's.
>
> Here, "new" in the sense that it can't be mapped directly back to stuff
> that can already be expressed natively in C.
Okay.
>
>>> Also comes with its own drawbacks (code bloat, try/catch+throw is
>>> usually slow, use with care else program explodes, ...). [...]
>>
>> I cannot confirm your statements, especially in that generality.
>>
>> I recall we had bloat with templates on a specific platform in the
>> very early pre-standard era, when they were first supported. But we
>> didn't have any [noteworthy] speed degradation with exceptions (or
>> templates).
>
> The relative impact of try/catch is more modest.
Aha; I thought that this would have been the source of criticism.
>
> Typically, it results in every function having an unwind-handling stub
> for, in-case an exception is thrown, it can call any destructors or
> similar.
I've seen and heard of may ways in which exceptions have been used,
ranging from a single "catch all" in the main() function, to each
function instrumented. I will not judge about these extreme cases.
All I say is that you, as a software designer, have the options to
sensibly structure and instrument your code with exceptions.
There's also the characteristic that you may define exception types
(or use just existing ones); build or add to a hierarchy to handle
them flexibly, provide context data with the exception objects, etc.
Handling all that manually and explicitly, without the support of an
exception concept I'd certainly not prefer.
Janis
> [...]
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-29 05:20 -0500 |
| Message-ID | <10vbp99$31nv$1@dont-email.me> |
| In reply to | #399485 |
On 5/29/2026 2:52 AM, Janis Papanagnou wrote:
> On 2026-05-28 11:57, BGB wrote:
>> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>>> On 2026-05-28 01:49, BGB wrote:
> [...]
>>> I'm a big fan of abstractions. - So many things beyond "C" are fine!
>>
>> I am not saying that abstractions are bad, but I haven't usually found
>> them to be worth the costs IME.
>
> Wow! - That's completely different from my experience and practice.
>
> It's what makes usage simple, fast, reliable. Not wasting time for
> details, or fixing technical bugs that should be prevented by the
> language.
>
Possibly.
But, it is also possible I approach programming in a different way.
>>
>>>> [...]
>>>>
>>>> Similar reason to why one doesn't build complex patterns or do
>>>> template- like stuff via function macros in the C preprocessor:
>>>> One can do this... But again, bloated binaries and terrible build
>>>> times.
>>>
>>> Code patterns that are bulky in "C" can be formulated tersely with
>>> C++/STL (while still preserving an efficient implementation, even with
>>> complexities guaranteed); and the framework is flexible, orthogonally
>>> designed. Easy to reuse high-level concepts as opposed to re-implement
>>> the same code for different types. Or weaken the code by extensive use
>>> of casts. All sorts of C's problems with memory can be addressed. (The
>>> list can be continued; but I wonder why such things aren't recognized.)
>>
>> Both have a similar issue when used in a naive way though:
>> Non-careful use of either results in code bloat.
>
> Okay, "when used in a in a naive way". - Let's leave it at that,
> then.
>
>>
>> But, not really an "easy" way to avoid bloat, other than to write code
>> specifically for what cases are relevant; while also avoiding needless
>> duplication and copy paste (where, overuse of copy/paste can also lead
>> to bloat; along with turning the code into an ugly mess).
>
> Hmm.. - as said, the during very early days there were issues; I
> recall on one platform duplication of template code in more that
> one source unit. And/or some environmental hacks (of the compiler)
> to deposit template code for linking. In the later days I've not
> seen such immature things anymore.
>
Possibly, a lot could depend on how one is counting things as well.
In a lot of cases when using GCC, I end up using:
-ffunction-sections -fdata-sections -Wl,-gc-sections
Because otherwise it likes wasting code space by retaining unreachable
functions.
Using "static inline" functions also carries a risk because the can end
up duplicated across multiple translation units, or in multiple places
within the same translation unit, so is best used sparingly.
>>
>> But, OTOH, factoring things into too small of pieces can negatively
>> effect performance (and, for non-leaf functions, prolog/epilog costs
>> for too many tiny functions can also be a source of code bloat).
>>
>> As can be noted, trying to mimic templates via creative use of C
>> preprocessor macros can also easily result in excessive bloat...
>>
>>>>
>>>> So, one is back to the core issue:
>>>> The part that is actually usable, mostly still amounts to syntactic
>>>> sugar over things you can already do in C.
>>>
>>> Huh? It may depend on the developer/programmer. But it's certainly a
>>> lot more than "syntactic sugar".
>>
>> Well, for example:
>> Operator overloading:
>> Basically glorified function calls made to resemble operators;
>> Classes:
>> Can be done with structs, and implementing vtables manually.
>>
>> Implementing class hierarchies via structs can be done, but gets ugly
>> (GTK's GObject system sorta went this way).
>
> We obviously disagree completely in what's "syntactic sugar".
>
> (With that reasoning all ("C" or other languages') features are
> "syntactic sugar" because you can do that also with assembly?)
>
To be excluded from being syntactic sugar, it needs to be something that
is not generally possible to express within the base language.
So, for example:
Things like operator overloading or classes are syntactic sugar IMO, as
what they do can be expressed in C, even if a lot less pretty (or far
from an idiomatic style).
I would not consider exceptions or RTTI as syntactic sugar, because
these involve things that do not map to native C.
Using longjmp, pointer-tagging, etc, could be considered as analogous,
but not functionally equivalent, to what C++ is doing in these cases.
As for assembler:
Main reasons not to use assembler for everything:
Needlessly verbose;
Non-portable.
However, often one can still end up writing C code that looks like
assembler sometimes, as this is often an effective way to optimize things.
Say, for example:
v0=cs[0];
v2=cs[2];
v1=cs[1];
v3=vs[3];
ct[0]=v0;
ct[2]=v2;
ct[1]=v1;
ct[3]=v3;
Vs:
ct[0]=cs[0];
ct[1]=cs[1];
ct[2]=cs[2];
ct[3]=cs[3];
Because the extra variables can avoid help sidestep latency from the
load instructions and staggering stores can avoid penalties of two
adjacent stores to the same cache-line in some cache architectures.
Where, in the latter case, the compiler may fail to as effectively avoid
the load-latency or realize the need to stagger the stores for best
performance, ...
>>>>
>>>> There are "niceties", granted, but relatively little "actually new".
>>>
>>> Not all concepts are "new", of course; we saw them in other languages
>>> years or (in some cases) decades ago. But C++' and STL features are a
>>> lot more than just niceties; it's beyond me how one may come to such
>>> a valuation. (And now let's compare that formulated demand or wish of
>>> new things with "C"?)
>>
>> Well, it is a thing that can be done, but is a double-edged sword.
>> Saves code one might have to write out manually.
>> But, is very easy to result in things that negatively effect build times.
>
> A simple, less-abstracted language can certainly be easier (thus
> faster) translated to machine code.
>
> I don't know about your working contexts. In our contexts slightly
> larger built-times were no issue. For one, we built using makefiles,
> and only full builds (to create QA test images, or public releases)
> required much time; they typically ran over night; our systems were
> typically very large!
>
> Build times were also influenced by other more significant factors.
> Mundane sounding things like ordering of functions in libraries and
> some such. (Though nothing that wouldn't have been possible to be
> addressed by the build-management group.)
>
I mostly do stuff myself. But, long build times can kill momentum.
In some cases, it is unavoidable, for example, Vivado takes 40 minutes
to synthesize an FPGA design, and Verilator may take multiple hours of
running to know whether or not something worked.
This sucks, but little I can do about this.
I do most of my software level testing in an emulator though, which does
at least have a fast turn-around...
Can't run my C compiler on my custom target though, as sadly, it is too
big and slow (would use too much RAM and take too long to run).
As noted, my compiler is around 370 kLOC.
Overall project size is a few MLOC.
Granted, my compiler has grown a few things related to resource/asset
packaging as well, so it also among other things works as an image
format converter, audio format converter, data packaging tool, and has
some wacky appendages like a SCAD interpreter and CSG geometry stuff
glued on (even if, yeah, interpreting SCAD and processing CSG models has
little to do with compiling stuff).
Sometimes one would prefer the code to be smaller, but sometimes it is not.
Some of my older code has vestiges of a lot of rampant copy/paste
though. Not ideal. And in my case my compiler, at its core, has its
basis in code I wrote in high-school (back when my coding skills left
something to be desired). Compiler is many layers of rampant hackery though.
It is more a case of "too bad it isn't less of a mess", but then efforts
to replace it had mostly fizzled; and the core design of the compiler
does seem to work effectively.
>>
>> Usual strategy is to try to limit how much code is written, and also
>> to avoid doing things in ways that result in too much code, or too
>> much cruft.
>>
>> Best to avoid both copy paste when reasonable, and sticking anything
>> non-trivial in macros.
>
> We avoided macros if possible.
>
They are de-facto for constants and similar, but for longer stuff is
better avoided.
#define FOO(arg) \
if(1) { \
... big blob of crap ... \
}
Being one of those, "yeah, don't do this" things.
Like, if a person finds themselves tempted to do this, maybe step back
and try to figure out how one ended up in this situation and if there is
a way out. If people start doing this too much, the code turns to crap.
I once implemented a VM backend where I did this a lot, it did not end
well. Managed to get a VM interpreter that, while fast, took a painfully
long time to compile due to all the excessive code generated via macros.
Now stuff mostly just sucks due to other reasons.
>>
>>>> And, one of the rare few "actually new" features C++ offers:
>>>> exceptions.
>>>
>>> We used them already in the 1990's.
>>
>> Here, "new" in the sense that it can't be mapped directly back to
>> stuff that can already be expressed natively in C.
>
> Okay.
>
>>
>>>> Also comes with its own drawbacks (code bloat, try/catch+throw is
>>>> usually slow, use with care else program explodes, ...). [...]
>>>
>>> I cannot confirm your statements, especially in that generality.
>>>
>>> I recall we had bloat with templates on a specific platform in the
>>> very early pre-standard era, when they were first supported. But we
>>> didn't have any [noteworthy] speed degradation with exceptions (or
>>> templates).
>>
>> The relative impact of try/catch is more modest.
>
> Aha; I thought that this would have been the source of criticism.
>
>>
>> Typically, it results in every function having an unwind-handling stub
>> for, in-case an exception is thrown, it can call any destructors or
>> similar.
>
> I've seen and heard of may ways in which exceptions have been used,
> ranging from a single "catch all" in the main() function, to each
> function instrumented. I will not judge about these extreme cases.
> All I say is that you, as a software designer, have the options to
> sensibly structure and instrument your code with exceptions.
>
> There's also the characteristic that you may define exception types
> (or use just existing ones); build or add to a hierarchy to handle
> them flexibly, provide context data with the exception objects, etc.
> Handling all that manually and explicitly, without the support of an
> exception concept I'd certainly not prefer.
>
Well, even when exceptions are not used by a program, one may still see
a size delta of a few percent by enabling or disabling them...
But, ironically, I am not totally opposed to exceptions, as they can
serve a purpose...
Well, even if sometimes they just amount to a missed uncaught exception
nuking the program...
But, things can be considered in relative terms:
Like, C++ may carry various penalties vs C.
But, like, it is still going to run circles around something like Python
or Node.js ...
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-05-29 13:22 +0200 |
| Message-ID | <10vbsua$1cre$1@dont-email.me> |
| In reply to | #399489 |
On 29/05/2026 12:20, BGB wrote:
> On 5/29/2026 2:52 AM, Janis Papanagnou wrote:
>> On 2026-05-28 11:57, BGB wrote:
>>> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>>>> On 2026-05-28 01:49, BGB wrote:
>> [...]
>>>
>>> But, not really an "easy" way to avoid bloat, other than to write
>>> code specifically for what cases are relevant; while also avoiding
>>> needless duplication and copy paste (where, overuse of copy/paste can
>>> also lead to bloat; along with turning the code into an ugly mess).
>>
>> Hmm.. - as said, the during very early days there were issues; I
>> recall on one platform duplication of template code in more that
>> one source unit. And/or some environmental hacks (of the compiler)
>> to deposit template code for linking. In the later days I've not
>> seen such immature things anymore.
>>
>
> Possibly, a lot could depend on how one is counting things as well.
>
>
> In a lot of cases when using GCC, I end up using:
> -ffunction-sections -fdata-sections -Wl,-gc-sections
On many targets, "-fdata-sections" can lead to noticeably larger and
slower code because it effectively eliminates section anchor
optimisations. It does not negatively affect x86 AFAICS, because x86
does not use section anchors.
<https://godbolt.org/z/zeoq41Y7d>
With -fsection-anchors (enabled with optimisation on targets that
support it - generally RISCy load/store architectures), program-lifetime
variables are kept together in a lump (as though they were in a struct)
and often addressed by a pointer to that pretend struct. Thus if a
function accesses two variables "a" and "b", instead of having to load
the addresses of each of "a" and "b" into separate registers, it loads
an "anchor" into one register and accesses the variables with reg+offset
addressing.
I've seen "-fdata-sections" used regularly in embedded systems - it is
almost always a bad idea.
("-ffunction-sections" is often very helpful to reduce code image size,
so keep that one.)
>
> Because otherwise it likes wasting code space by retaining unreachable
> functions.
>
> Using "static inline" functions also carries a risk because the can end
> up duplicated across multiple translation units, or in multiple places
> within the same translation unit, so is best used sparingly.
>
Usually you would only use static inline functions for small functions
in headers, where they are a better choice than function-like macros.
In a C file, there is rarely much point in declaring a function "inline"
- optimising compilers will inline or not as they see fit, without
regard for "inline". "static" on its own is, of course, always a good
idea for functions or data that is not "exported" by the current
translation unit, and will often make generated code smaller.
How much or how little duplication of code there will be within one
translation unit will depend on compiler settings and the rest of the
code, and not on whether or not you use "inline".
>
>
> As for assembler:
> Main reasons not to use assembler for everything:
> Needlessly verbose;
> Non-portable.
>
> However, often one can still end up writing C code that looks like
> assembler sometimes, as this is often an effective way to optimize things.
>
> Say, for example:
> v0=cs[0];
> v2=cs[2];
> v1=cs[1];
> v3=vs[3];
> ct[0]=v0;
> ct[2]=v2;
> ct[1]=v1;
> ct[3]=v3;
> Vs:
> ct[0]=cs[0];
> ct[1]=cs[1];
> ct[2]=cs[2];
> ct[3]=cs[3];
>
> Because the extra variables can avoid help sidestep latency from the
> load instructions and staggering stores can avoid penalties of two
> adjacent stores to the same cache-line in some cache architectures.
> Where, in the latter case, the compiler may fail to as effectively avoid
> the load-latency or realize the need to stagger the stores for best
> performance, ...
That might be the case for a very simplistic compiler. With an
optimising compiler, these extra variables will quickly be eliminated.
If the compiler has a good scheduling model of the device, it do
whatever instruction scheduling works best for that processor. If the
model is not good enough, it will be suboptimal. I would not, however,
expect any different in the generated code for the two code snippets.
Sometimes this kind of "manual optimisation" is helpful when you have to
try to get efficient results from a weak compiler, however.
>
>>>
>>> Usual strategy is to try to limit how much code is written, and also
>>> to avoid doing things in ways that result in too much code, or too
>>> much cruft.
>>>
>>> Best to avoid both copy paste when reasonable, and sticking anything
>>> non-trivial in macros.
>>
>> We avoided macros if possible.
>>
>
> They are de-facto for constants and similar, but for longer stuff is
> better avoided.
Macros are rarely the best way to define constants. They are needed if
you are using the constants for pre-processor stuff like conditional
compilation. But generally you get clearer code, better typing, and
potentially several other benefits from using alternative choices like
"enum" (even for stand-alone integer constants), "static const"
variables, and in C23, "constexpr" variables. There's no doubt that a
lot of code /does/ use macros for constants, but I view it as a relic of
the past rather than good coding practice.
>
>
> But, things can be considered in relative terms:
> Like, C++ may carry various penalties vs C.
>
I don't find C++ carries noticeably penalties compared to C, for my
embedded work. But I do disable exceptions and RTTI - exceptions may
have very little run-time time overhead, but the unwind tables can be
significant when code size is important in small systems.
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-29 15:16 -0500 |
| Message-ID | <10vcs7o$d8e9$1@dont-email.me> |
| In reply to | #399491 |
On 5/29/2026 6:22 AM, David Brown wrote:
> On 29/05/2026 12:20, BGB wrote:
>> On 5/29/2026 2:52 AM, Janis Papanagnou wrote:
>>> On 2026-05-28 11:57, BGB wrote:
>>>> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>>>>> On 2026-05-28 01:49, BGB wrote:
>>> [...]
>
>>>>
>>>> But, not really an "easy" way to avoid bloat, other than to write
>>>> code specifically for what cases are relevant; while also avoiding
>>>> needless duplication and copy paste (where, overuse of copy/paste
>>>> can also lead to bloat; along with turning the code into an ugly mess).
>>>
>>> Hmm.. - as said, the during very early days there were issues; I
>>> recall on one platform duplication of template code in more that
>>> one source unit. And/or some environmental hacks (of the compiler)
>>> to deposit template code for linking. In the later days I've not
>>> seen such immature things anymore.
>>>
>>
>> Possibly, a lot could depend on how one is counting things as well.
>>
>>
>> In a lot of cases when using GCC, I end up using:
>> -ffunction-sections -fdata-sections -Wl,-gc-sections
>
> On many targets, "-fdata-sections" can lead to noticeably larger and
> slower code because it effectively eliminates section anchor
> optimisations. It does not negatively affect x86 AFAICS, because x86
> does not use section anchors.
>
> <https://godbolt.org/z/zeoq41Y7d>
>
> With -fsection-anchors (enabled with optimisation on targets that
> support it - generally RISCy load/store architectures), program-lifetime
> variables are kept together in a lump (as though they were in a struct)
> and often addressed by a pointer to that pretend struct. Thus if a
> function accesses two variables "a" and "b", instead of having to load
> the addresses of each of "a" and "b" into separate registers, it loads
> an "anchor" into one register and accesses the variables with reg+offset
> addressing.
>
> I've seen "-fdata-sections" used regularly in embedded systems - it is
> almost always a bad idea.
>
> ("-ffunction-sections" is often very helpful to reduce code image size,
> so keep that one.)
>
Both seem to help on x86, x86-64, and also on RISC-V, at making GCC's
output at least sorta space-comparable to my own compilers.
The merit of "-fdata-sections" is mostly that it eliminates unused
global variables; whereas "-ffunction-sections" eliminates unreachable
functions.
Neither is needed with my own compiler, which compiles things in a way
such that it eliminates anything that is unreachable.
Both posed an issue initially when porting ROTT, because in some cases
it relied on the ability to go out-of-bounds for one array to access
data in another array. I ended up reworking some of these cases though
to use a single larger array.
Have noted though that GCC targeting RISC-V still tends to produce
fairly large binaries even with "-Os". Its code for the basic subset
(RV64G) does tend to be a little faster than what BGBCC generates, but
also a fair bit more bulky. Though, the final ELF file ends up bigger
still, as a significant chunk of the file ends up needing to hold ELF
related metadata (comparably, PE/COFF can end up much leaner here).
Though, on the other side, with modern MSVC, despite the relative
leanness of the PE/COFF format, MSVC tends to produce binaries with much
larger ".text" sections.
This issue was a lot less with VS2008 though, which tended to generate
less-bloated binaries (with code-size more competitive with GCC).
Also in modern MSVC, there is little distinction between "/O1" and
"/Os", both being more space-efficient than "/O2" (though, "/O2" is
usually faster, but also more prone to misguided attempts at
auto-vectorization).
>
>
>>
>> Because otherwise it likes wasting code space by retaining unreachable
>> functions.
>>
>> Using "static inline" functions also carries a risk because the can
>> end up duplicated across multiple translation units, or in multiple
>> places within the same translation unit, so is best used sparingly.
>>
>
> Usually you would only use static inline functions for small functions
> in headers, where they are a better choice than function-like macros. In
> a C file, there is rarely much point in declaring a function "inline" -
> optimising compilers will inline or not as they see fit, without regard
> for "inline". "static" on its own is, of course, always a good idea for
> functions or data that is not "exported" by the current translation
> unit, and will often make generated code smaller.
>
> How much or how little duplication of code there will be within one
> translation unit will depend on compiler settings and the rest of the
> code, and not on whether or not you use "inline".
>
OK.
But, yeah, small functions are usually better than macros in at least
that the compiler can avoid duplicating them (or maybe merge them
between translation units when it notices that the contents are identical).
>
>>
>>
>> As for assembler:
>> Main reasons not to use assembler for everything:
>> Needlessly verbose;
>> Non-portable.
>>
>> However, often one can still end up writing C code that looks like
>> assembler sometimes, as this is often an effective way to optimize
>> things.
>>
>> Say, for example:
>> v0=cs[0];
>> v2=cs[2];
>> v1=cs[1];
>> v3=vs[3];
>> ct[0]=v0;
>> ct[2]=v2;
>> ct[1]=v1;
>> ct[3]=v3;
>> Vs:
>> ct[0]=cs[0];
>> ct[1]=cs[1];
>> ct[2]=cs[2];
>> ct[3]=cs[3];
>>
>> Because the extra variables can avoid help sidestep latency from the
>> load instructions and staggering stores can avoid penalties of two
>> adjacent stores to the same cache-line in some cache architectures.
>> Where, in the latter case, the compiler may fail to as effectively
>> avoid the load-latency or realize the need to stagger the stores for
>> best performance, ...
>
> That might be the case for a very simplistic compiler. With an
> optimising compiler, these extra variables will quickly be eliminated.
> If the compiler has a good scheduling model of the device, it do
> whatever instruction scheduling works best for that processor. If the
> model is not good enough, it will be suboptimal. I would not, however,
> expect any different in the generated code for the two code snippets.
>
> Sometimes this kind of "manual optimisation" is helpful when you have to
> try to get efficient results from a weak compiler, however.
>
Possibly, but this sort of thing can help with both BGBCC and with MSVC IME.
While BGBCC does use a shuffle-to-reorder instructions things, it may
fail to do so in some cases:
If the instructions end up mapped to the same CPU register;
If its heuristics can't prove non-alias.
Though, in the simple example given, it could (probably) turn the latter
into the former, but "better" to write code such that things are in
closer to the optimal order by default.
Note that using different variables with overlapping scopes reduces the
likelihood of the compiler assigning both to the same register, which is
a much more real risk if relying on implicit temporaries (whose lifetime
only exists within a single expression).
But, in my case, a lot of this comes down to trying to tweak the
compilers' internal register allocation heuristics for best results (and
the tight balance between how many registers to save/restore for the
function, vs avoiding assigning short-lived temporaries to the same
register too quickly and hindering the instruction-scheduling).
Arguably, could make sense to instead do the reordering at the 3AC
level, rather than reordering at the level of ISA instructions, but this
is just sorta how I ended up doing things (and one can know the
effective timing latency of a CPU instruction a lot more easily than a
3AC op).
>
>>
>>>>
>>>> Usual strategy is to try to limit how much code is written, and also
>>>> to avoid doing things in ways that result in too much code, or too
>>>> much cruft.
>>>>
>>>> Best to avoid both copy paste when reasonable, and sticking anything
>>>> non-trivial in macros.
>>>
>>> We avoided macros if possible.
>>>
>>
>> They are de-facto for constants and similar, but for longer stuff is
>> better avoided.
>
> Macros are rarely the best way to define constants. They are needed if
> you are using the constants for pre-processor stuff like conditional
> compilation. But generally you get clearer code, better typing, and
> potentially several other benefits from using alternative choices like
> "enum" (even for stand-alone integer constants), "static const"
> variables, and in C23, "constexpr" variables. There's no doubt that a
> lot of code /does/ use macros for constants, but I view it as a relic of
> the past rather than good coding practice.
>
They are traditional...
Like:
static const double M_PI = 3.14159265358979;
Could also make sense, but people don't do usually this, they usually
use macros...
In BGBCC, both can be handled as constants, just they end up being
handled at different stages:
#define: Constant ends up inlined in the preprocessor/parse stage;
const: Constant shows up in the "reducer" (which evaluates constant
expressions).
Where, as noted, BGBCC's pipeline looks kinda like:
Toplevel:
Ingest each named source file;
Then, in the C case, per translation unit:
Preprocess;
Parse;
Frontend Compile + Reduce;
This does an AST walk, but at each stage,
invokes the reducer to see if it can perform AST level rewrites;
Reducer can also implement some edge-case features.
So, is mostly necessary, vs an optional optimization thing.
Emits output as a Stack IL.
May be output to a file, or used as input to next stage.
The stack IL partly resembles a mix of JVM and .NET bytecode.
The IL ops themselves operate more like in .NET bytecode.
This serves the role of static libraries and object files.
For a static library, all the stack IL gets blobbed together.
So, every translation unit ends up effectively appended on.
Middle Stage (processes IL Blobs):
Processes Stack IL, translates to 3AC (loosely SSA form);
Builds a big table of all global declarations, etc.
Backend:
Walks call-graph to determine dependencies;
Unreachable functions/globals/etc are marked as culled.
Ranks all the functions and variables by priority;
Sorts them into roughly priority order;
Then does shuffling to try to density-optimize globals;
Swaps globals when doing so would allow more memory density.
May also apply random shuffling and clustering heuristics.
Then, compiles each function:
Figure out stack-frame layout,
how many registers to reserve,
etc.
Emit machine code for 3AC ops;
Try to shuffle instructions to improve instruction scheduling;
Or, if a variable:
Figure out whether it goes in ".data" or ".bss"
If initialized, deal with initialization stuff;
...
Or, an ASM Blob:
Assemble it.
Or, Ingests contents that go into ".rsrc" section;
May involve image and audio converters, etc;
BGBCC uses different resource sections from Windows though.
...
Output:
Gets is input as a set of sections, symbols, and relocs;
Figures out layout within the output image (eg, PE/COFF);
Figures out how much space it needs for base relocs, etc.
Builds up a table of "initial base-relocs"
Splats the sections into the image buffer;
Applies relevant relocs;
Sorts base relocs by RVA;
Generates actual ".reloc" section contents.
Fill in PE/COFF headers and similar;
If applicable, LZ4 compress the image.
I tend to store EXE's in LZ4 compressed form,
the image is decompressed during load.
This format leaves the initial PE/COFF headers uncompressed.
Need the headers to figure out where to load the image.
Else would need a temporary buffer to decompress into.
Typical loader process:
Look at headers;
Figure out where to load to, etc;
Read in (or decompress) image contents;
Apply base relocs;
Pull in any DLLs, etc;
Go.
The LZ4 compression is mostly because:
Loader is often IO bound;
May save memory in some cases;
LZ4 decompression is faster than more IO;
It also seems to be effective against program binaries (*).
*: I have my RP2 format, which generally does better for general purpose
data compression, but slightly worse for compressing program binaries,
so LZ4 has mostly won here. Also generally don't want a "stronger"
compressor, like Deflate, both because an Inflater is a much bigger
chunk of code, and also much slower than LZ4.
Can note that BGBCC also mostly takes over the role of the "resource
compiler" as well, so can process resources. These are generally listed
as a text file of entries to import, giving an internal "lumpname",
external filename, and a tag to specify which file conversions to apply.
I am using a vert different resource section type than Windows though,
in that I just sorta replaced it with a modified version of the Quake
WAD2 format (not to be confused with PAK, where PAK serves a different
role). Note that the WAD2 directory in this case uses RVA's and not
WAD-file offsets (so, effectively, it is integrated into the PE/COFF
image, not just a WAD file that was shoved in).
Generally, one can access lumps from C land with declarations like:
extern unsigned char __rsrc_lumpname[];
Typically, formats used internally are things like BMP and WAV. Though,
when using BMP, it is typically 16 color or 256 color to avoid wasting
space. Sometimes monochrome or 4 color. One downside of BMP is that for
a full 256-color palette it needs 1K of memory just for the palette,
tempting to consider a non-standard variant that uses RGB555 for the
palette (thus reducing it to 512 bytes). For small images it is often
smaller to store them as 16-bit hi-color to avoid the space penalty of
the color palette.
There are already non-standard BMP variants though, like BMP with LZ
compression. A lot depends on what is needed for a particular use-case.
For WAV typical formats are 2 or 4 bit ADPCM at 8/11/16 kHz.
2 bit ADPCM: 16/22/32 kbps.
4 bit ADPCM: 32/44/64 kbps.
Have found encoder-side tricks to make ADPCM more compressible with LZ4.
Basically, it tries to do a reverse LZ search when encoding and encodes
audio following patterns when the pattern would be a "close enough" match.
had also experimented before with using some trickery involving FIR
filters and lookup tables to improve perceptual quality of 8kHz/2b ADPCM
to try to make it sound "less like total crap". But, this requires
additional metadata and a more complex process to decode (and to get
best results with this will result in worse audio quality if the audio
is just naively decoded as 8kHz/2b ADPCM without the filters).
But, yeah, with these tricks can reduce the effective bitrate (when LZ4
compressed) down to around 8-12 kbps. Note that while entropy coding
could help more, it is modest, and the most effective strategy (range
coding) being mostly too slow to be worthwhile.
Also, of the things I have tested, ADPCM was still the front runner for
"actually passable" audio quality in this domain (to me, some of the
modern cellphone codecs sound like unintelligible broken garbage, and
require much more complex decoders, not worth the bother).
only thing I have found that gets much lower bitrate is, say:
One divides the audio up into chunks of 64 samples (1/125 second for 8kHz);
Pick the top 4 square-waves from between 1 and 4 kHz;
Encode the phase and intensity of each square wave.
Typically, the strategy was to break it into 4 half-octaves and pick the
highest peak in each half-octave; and then totally ignore everything
below 1kHz. If the frequency and amplitude are encoded in around 16 bits
each, this achieves an effective bitrate of 8 kbps.
Though, another strategy was 8 quarter octaves and pick the top 4 loudest.
But, audio quality is worse than 2b ADPCM.
Can push it to 4kbps by only encoding the top 2 waveforms.
But, then speech sounds robotic and borderline unintelligible.
Note that dropping to 62.5 Hz sampling also makes speech unintelligible.
While traditionally, this used sine-waves (sinewave synthesis) I had
better results with square waves (simpler/cheaper, also better results
audio-wise). Computational cost for decoding is fairly modest (mostly
some "for()" loops and fixed-point arithmetic).
Though, effective bitrate may be lower, because it seems that speech
encoded this way is often LZ compressible as well (and can be helped
along with pattern matching tricks).
...
But, yeah, generally want images and audio to be fairly compact when
shoving them inside an EXE or DLL, for more general asset data,
generally better to use an external file.
I had often used a custom "WAD4" format here, which is kinda like "WAD2
but with longer names and a directory tree". It then exists as a lower
cost option to the ZIP format (while semi-popular, ZIP is a
high-overhead format to be used this way).
Also can use WAD4 as a sort of VFS packaging.
>>
>>
>> But, things can be considered in relative terms:
>> Like, C++ may carry various penalties vs C.
>>
>
> I don't find C++ carries noticeably penalties compared to C, for my
> embedded work. But I do disable exceptions and RTTI - exceptions may
> have very little run-time time overhead, but the unwind tables can be
> significant when code size is important in small systems.
>
Yes, that is the main thing.
They carry zero performance penalty in practice;
But, have a non-zero penalty for image size.
Not enough to be a deal-breaker towards using them if they are used, but
enough that one wants them disabled if not used...
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-05-30 13:52 +0200 |
| Message-ID | <10vej2c$qmam$1@dont-email.me> |
| In reply to | #399514 |
On 29/05/2026 22:16, BGB wrote:
> On 5/29/2026 6:22 AM, David Brown wrote:
>> On 29/05/2026 12:20, BGB wrote:
>>> On 5/29/2026 2:52 AM, Janis Papanagnou wrote:
>>>> On 2026-05-28 11:57, BGB wrote:
>>>>> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>>>>>> On 2026-05-28 01:49, BGB wrote:
>>>> [...]
>>
>>>>>
>>>>> But, not really an "easy" way to avoid bloat, other than to write
>>>>> code specifically for what cases are relevant; while also avoiding
>>>>> needless duplication and copy paste (where, overuse of copy/paste
>>>>> can also lead to bloat; along with turning the code into an ugly
>>>>> mess).
>>>>
>>>> Hmm.. - as said, the during very early days there were issues; I
>>>> recall on one platform duplication of template code in more that
>>>> one source unit. And/or some environmental hacks (of the compiler)
>>>> to deposit template code for linking. In the later days I've not
>>>> seen such immature things anymore.
>>>>
>>>
>>> Possibly, a lot could depend on how one is counting things as well.
>>>
>>>
>>> In a lot of cases when using GCC, I end up using:
>>> -ffunction-sections -fdata-sections -Wl,-gc-sections
>>
>> On many targets, "-fdata-sections" can lead to noticeably larger and
>> slower code because it effectively eliminates section anchor
>> optimisations. It does not negatively affect x86 AFAICS, because x86
>> does not use section anchors.
>>
>> <https://godbolt.org/z/zeoq41Y7d>
>>
>> With -fsection-anchors (enabled with optimisation on targets that
>> support it - generally RISCy load/store architectures), program-
>> lifetime variables are kept together in a lump (as though they were in
>> a struct) and often addressed by a pointer to that pretend struct.
>> Thus if a function accesses two variables "a" and "b", instead of
>> having to load the addresses of each of "a" and "b" into separate
>> registers, it loads an "anchor" into one register and accesses the
>> variables with reg+offset addressing.
>>
>> I've seen "-fdata-sections" used regularly in embedded systems - it is
>> almost always a bad idea.
>>
>> ("-ffunction-sections" is often very helpful to reduce code image
>> size, so keep that one.)
>>
>
> Both seem to help on x86, x86-64, and also on RISC-V, at making GCC's
> output at least sorta space-comparable to my own compilers.
>
> The merit of "-fdata-sections" is mostly that it eliminates unused
> global variables; whereas "-ffunction-sections" eliminates unreachable
> functions.
That is the point of them, yes. "-ffunction-sections" can be useful at
removing unused code from more general code. For microcontrollers,
SDK's and manufacturers' driver code will normally contain a large
number of functions that can be eliminated in this way, saving a lot of
code space.
However, in practice, "-fdata-sections" rarely eliminates a significant
amount - most programs do not have large amounts of statically-allocated
data that is not used. Gcc, and I think most other compilers, put the
static lifetime data for each translation unit in its own section, so if
no data from a translation unit is used it will be eliminated at link
time even with -fno-data-sections. And of course it makes no difference
for heap data or stack data.
In my testing, "-ffunction-sections" is absolutely worth using (on
targets where code space is relevant - there's no need for PC software).
On some targets, it may mean a few lost opportunities for shorter
jump/call instructions between functions in the same translation unit,
but the cost is rarely anything more than a slightly longer link time.
But "-fdata-sections" typically gives almost no ram space savings, and
makes code bigger and slower.
As I noted, gcc on x86 does not support section anchors, so there is not
likely to be much code cost for -ffdata-sections.
Where section anchors shine - and where -fdata-sections therefore has
cost - is when a function needs to access more than one piece of static
lifetime data defined in the same translation unit (or another
translation unit if you are using LTO). That happens a lot in embedded
ARM programming at least. I don't know about RISC-V. If the target
normally uses a "small data section" for ram (I know this is common on
PowerPC), then there is, in effect, a program-wide section anchor
already. So it is possible that it relatively few targets have section
anchors - but the 32-bit ARM on gcc is a vastly popular choice in the
embedded world, so it is important to understand the cost of this
compiler flag for that target at least.
>
> Neither is needed with my own compiler, which compiles things in a way
> such that it eliminates anything that is unreachable.
[...]
>>
>> That might be the case for a very simplistic compiler. With an
>> optimising compiler, these extra variables will quickly be eliminated.
>> If the compiler has a good scheduling model of the device, it do
>> whatever instruction scheduling works best for that processor. If the
>> model is not good enough, it will be suboptimal. I would not,
>> however, expect any different in the generated code for the two code
>> snippets.
>>
>> Sometimes this kind of "manual optimisation" is helpful when you have
>> to try to get efficient results from a weak compiler, however.
>>
>
> Possibly, but this sort of thing can help with both BGBCC and with MSVC
> IME
I don't tend to think of MSVC as a highly optimising compiler - but it
is not a tool I have much use for, as it does not handle the targets I
need. When I have sometimes looked at the generated code on godbolt, it
has not impressed me at all. So it could well fall into the "helpful
when using a weaker compiler" category.
>
>>
>>>
>>>>>
>>>>> Usual strategy is to try to limit how much code is written, and
>>>>> also to avoid doing things in ways that result in too much code, or
>>>>> too much cruft.
>>>>>
>>>>> Best to avoid both copy paste when reasonable, and sticking
>>>>> anything non-trivial in macros.
>>>>
>>>> We avoided macros if possible.
>>>>
>>>
>>> They are de-facto for constants and similar, but for longer stuff is
>>> better avoided.
>>
>> Macros are rarely the best way to define constants. They are needed
>> if you are using the constants for pre-processor stuff like
>> conditional compilation. But generally you get clearer code, better
>> typing, and potentially several other benefits from using alternative
>> choices like "enum" (even for stand-alone integer constants), "static
>> const" variables, and in C23, "constexpr" variables. There's no doubt
>> that a lot of code /does/ use macros for constants, but I view it as a
>> relic of the past rather than good coding practice.
>>
>
> They are traditional...
>
> Like:
> static const double M_PI = 3.14159265358979;
>
> Could also make sense, but people don't do usually this, they usually
> use macros...
They should not do so (IMHO, of course). Yes, macros are traditional -
but there are no plus sides to using them for this kind of thing.
(There are no plus sides to using all-caps either, but people do that too.)
(I'm snipping all the details of your own C compiler, because there is
very little I can comment on.)
>
>>>
>>>
>>> But, things can be considered in relative terms:
>>> Like, C++ may carry various penalties vs C.
>>>
>>
>> I don't find C++ carries noticeably penalties compared to C, for my
>> embedded work. But I do disable exceptions and RTTI - exceptions may
>> have very little run-time time overhead, but the unwind tables can be
>> significant when code size is important in small systems.
>>
>
> Yes, that is the main thing.
> They carry zero performance penalty in practice;
> But, have a non-zero penalty for image size.
>
> Not enough to be a deal-breaker towards using them if they are used, but
> enough that one wants them disabled if not used...
>
Agreed.
(I could also note that I make heavy use of templates in C++ code - it
often leads to smaller and faster results.)
[toc] | [prev] | [next] | [standalone]
| From | Janis Papanagnou <janis_papanagnou+ng@hotmail.com> |
|---|---|
| Date | 2026-05-30 14:40 +0200 |
| Message-ID | <10velsp$3uus8$8@dont-email.me> |
| In reply to | #399534 |
On 2026-05-30 13:52, David Brown wrote: > On 29/05/2026 22:16, BGB wrote: >> On 5/29/2026 6:22 AM, David Brown wrote: >>> On 29/05/2026 12:20, BGB wrote: >>>> On 5/29/2026 2:52 AM, Janis Papanagnou wrote: >>>>> >>>>> We avoided macros if possible. >>>> >>>> They are de-facto for constants and similar, but for longer stuff is >>>> better avoided. >>> >>> Macros are rarely the best way to define constants. They are needed >>> if you are using the constants for pre-processor stuff like >>> conditional compilation. But generally you get clearer code, better >>> typing, and potentially several other benefits from using alternative >>> choices like "enum" (even for stand-alone integer constants), "static >>> const" variables, and in C23, "constexpr" variables. There's no >>> doubt that a lot of code /does/ use macros for constants, but I view >>> it as a relic of the past rather than good coding practice. >> >> They are traditional... >> >> Like: >> static const double M_PI = 3.14159265358979; >> >> Could also make sense, but people don't do usually this, they usually >> use macros... > > They should not do so (IMHO, of course). Yes, macros are traditional - > but there are no plus sides to using them for this kind of thing. (There > are no plus sides to using all-caps either, but people do that too.) Because in early days Cpp constants have been used and Cpp-stuff often capitalized[*]. Our C++ coding rules back then had mandated lowercase also for constants, but strangely some folks were so used to uppercase Cpp literals that they disliked to write constants (as other objects) in lowercase, and stated opinions were sometimes heated like religious topics. I wonder what lexical convention regular "C" (or C++) programmers here use for constants nowadays. Curiously I inspected my latest C-source to see what convention I've actually followed recently. But I noticed that I had no hard constants used at all; all parameters came from a configuration file and through the command line interface. (That makes sense, I guess.) Janis [*] Strangely there were C-function-macros that were written lowercase, though. > [...]
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-05-30 16:36 +0200 |
| Message-ID | <10vesks$t981$1@dont-email.me> |
| In reply to | #399537 |
On 30/05/2026 14:40, Janis Papanagnou wrote: > On 2026-05-30 13:52, David Brown wrote: >> On 29/05/2026 22:16, BGB wrote: >>> On 5/29/2026 6:22 AM, David Brown wrote: >>>> On 29/05/2026 12:20, BGB wrote: >>>>> On 5/29/2026 2:52 AM, Janis Papanagnou wrote: >>>>>> >>>>>> We avoided macros if possible. >>>>> >>>>> They are de-facto for constants and similar, but for longer stuff >>>>> is better avoided. >>>> >>>> Macros are rarely the best way to define constants. They are needed >>>> if you are using the constants for pre-processor stuff like >>>> conditional compilation. But generally you get clearer code, better >>>> typing, and potentially several other benefits from using >>>> alternative choices like "enum" (even for stand-alone integer >>>> constants), "static const" variables, and in C23, "constexpr" >>>> variables. There's no doubt that a lot of code /does/ use macros >>>> for constants, but I view it as a relic of the past rather than good >>>> coding practice. >>> >>> They are traditional... >>> >>> Like: >>> static const double M_PI = 3.14159265358979; >>> >>> Could also make sense, but people don't do usually this, they usually >>> use macros... >> >> They should not do so (IMHO, of course). Yes, macros are traditional >> - but there are no plus sides to using them for this kind of thing. >> (There are no plus sides to using all-caps either, but people do that >> too.) > > Because in early days Cpp constants have been used and Cpp-stuff often > capitalized[*]. Our C++ coding rules back then had mandated lowercase > also for constants, but strangely some folks were so used to uppercase > Cpp literals that they disliked to write constants (as other objects) > in lowercase, and stated opinions were sometimes heated like religious > topics. > > I wonder what lexical convention regular "C" (or C++) programmers here > use for constants nowadays. > > Curiously I inspected my latest C-source to see what convention I've > actually followed recently. But I noticed that I had no hard constants > used at all; all parameters came from a configuration file and through > the command line interface. (That makes sense, I guess.) > > Janis > > [*] Strangely there were C-function-macros that were written lowercase, > though. > I think there is a reasonable case for all-caps for macros that are doing something "weird", as a warning to users. You know that it's risky trying to write "MAX(a++, b++)", as it might evaluate one or both of the parameter expressions twice. But if you also use all-caps for well-behaved macros, that dilutes the warning effect. I use all-caps for define names that I expect to come from outside the source files - like a command line flag "-DPROG_VARIANT=2" in a makefile, and that kind of thing. That, to me, counts as a "weird" macro. I am happy to use macros where they make sense, but I would not use a macro if a static const, enum, static inline function, or constexpr variable will do just as well.
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@gmail.com> |
|---|---|
| Date | 2026-05-30 15:48 -0500 |
| Message-ID | <10vfiet$13qfl$1@dont-email.me> |
| In reply to | #399534 |
On 5/30/2026 6:52 AM, David Brown wrote:
> On 29/05/2026 22:16, BGB wrote:
>> On 5/29/2026 6:22 AM, David Brown wrote:
>>> On 29/05/2026 12:20, BGB wrote:
>>>> On 5/29/2026 2:52 AM, Janis Papanagnou wrote:
>>>>> On 2026-05-28 11:57, BGB wrote:
>>>>>> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>>>>>>> On 2026-05-28 01:49, BGB wrote:
>>>>> [...]
>>>
>>>>>>
>>>>>> But, not really an "easy" way to avoid bloat, other than to write
>>>>>> code specifically for what cases are relevant; while also avoiding
>>>>>> needless duplication and copy paste (where, overuse of copy/paste
>>>>>> can also lead to bloat; along with turning the code into an ugly
>>>>>> mess).
>>>>>
>>>>> Hmm.. - as said, the during very early days there were issues; I
>>>>> recall on one platform duplication of template code in more that
>>>>> one source unit. And/or some environmental hacks (of the compiler)
>>>>> to deposit template code for linking. In the later days I've not
>>>>> seen such immature things anymore.
>>>>>
>>>>
>>>> Possibly, a lot could depend on how one is counting things as well.
>>>>
>>>>
>>>> In a lot of cases when using GCC, I end up using:
>>>> -ffunction-sections -fdata-sections -Wl,-gc-sections
>>>
>>> On many targets, "-fdata-sections" can lead to noticeably larger and
>>> slower code because it effectively eliminates section anchor
>>> optimisations. It does not negatively affect x86 AFAICS, because x86
>>> does not use section anchors.
>>>
>>> <https://godbolt.org/z/zeoq41Y7d>
>>>
>>> With -fsection-anchors (enabled with optimisation on targets that
>>> support it - generally RISCy load/store architectures), program-
>>> lifetime variables are kept together in a lump (as though they were
>>> in a struct) and often addressed by a pointer to that pretend struct.
>>> Thus if a function accesses two variables "a" and "b", instead of
>>> having to load the addresses of each of "a" and "b" into separate
>>> registers, it loads an "anchor" into one register and accesses the
>>> variables with reg+offset addressing.
>>>
>>> I've seen "-fdata-sections" used regularly in embedded systems - it
>>> is almost always a bad idea.
>>>
>>> ("-ffunction-sections" is often very helpful to reduce code image
>>> size, so keep that one.)
>>>
>>
>> Both seem to help on x86, x86-64, and also on RISC-V, at making GCC's
>> output at least sorta space-comparable to my own compilers.
>>
>> The merit of "-fdata-sections" is mostly that it eliminates unused
>> global variables; whereas "-ffunction-sections" eliminates unreachable
>> functions.
>
> That is the point of them, yes. "-ffunction-sections" can be useful at
> removing unused code from more general code. For microcontrollers,
> SDK's and manufacturers' driver code will normally contain a large
> number of functions that can be eliminated in this way, saving a lot of
> code space.
>
> However, in practice, "-fdata-sections" rarely eliminates a significant
> amount - most programs do not have large amounts of statically-allocated
> data that is not used. Gcc, and I think most other compilers, put the
> static lifetime data for each translation unit in its own section, so if
> no data from a translation unit is used it will be eliminated at link
> time even with -fno-data-sections. And of course it makes no difference
> for heap data or stack data.
>
The main place it makes a difference is global arrays from a translation
unit that is included, but for functions that are not included.
Also functions with large static arrays.
void SomeFunc()
{
static char buf[4096];
...
}
Where, say, eliminating SomeFunc does not necessarily eliminate buf.
> In my testing, "-ffunction-sections" is absolutely worth using (on
> targets where code space is relevant - there's no need for PC software).
> On some targets, it may mean a few lost opportunities for shorter
> jump/call instructions between functions in the same translation unit,
> but the cost is rarely anything more than a slightly longer link time.
> But "-fdata-sections" typically gives almost no ram space savings, and
> makes code bigger and slower.
>
> As I noted, gcc on x86 does not support section anchors, so there is not
> likely to be much code cost for -ffdata-sections.
>
> Where section anchors shine - and where -fdata-sections therefore has
> cost - is when a function needs to access more than one piece of static
> lifetime data defined in the same translation unit (or another
> translation unit if you are using LTO). That happens a lot in embedded
> ARM programming at least. I don't know about RISC-V. If the target
> normally uses a "small data section" for ram (I know this is common on
> PowerPC), then there is, in effect, a program-wide section anchor
> already. So it is possible that it relatively few targets have section
> anchors - but the 32-bit ARM on gcc is a vastly popular choice in the
> embedded world, so it is important to understand the cost of this
> compiler flag for that target at least.
>
It depends on the way it is built.
A lot of times though (for non-relocatable static-linked binaries) it
mostly tends to use AUIPC+LD or AUIPC+ST pairs to access global
variables. There is a Global Pointer that needs to be loaded when the
binary is started, unclear what it is used for exactly.
in PIC/PIE binaries, it uses AUIPC+ADDI to get a GOT pointer and then
uses the GOT pointers to access global variables (via fetching the
address of the variable from the GOT).
Can note that BGBCC targeting RV works differently, instead using GP to
access global variables, and clustering the commonly accessed global
variables around GP (GP is initialized to point towards at the start of
the ".data" section for the main EXE at program startup, though in my
ABI this may actually be a copy allocated elsewhere in RAM, and not
actually pointing at the version of the section located in the original
PE image; note that the loader also applies base relocs for the data
section separately when locating it; in effect the base relocs being
internally partitioned per-section, rather than the per-page
partitioning scheme used in the original PE/COFF).
For my target, I mostly end up needing to use PIE binaries with GCC, as
it needs to be able to load the binary at different locations.
However, I am using a custom C library, as I (still) haven't managed to
get the "ld-linux.so" stuff working. Not yet figured out whatever
poorly-documented arcane dark magic is needed to get this part working.
As noted, my compiler's output (including for plain RISC-V) using
PE/COFF, which was also the native format for the OS.
Note that for Linux binaries in this case it would mimics the Linux
syscall interface; though as I hadn't gotten very far with the PIE
loader, most of the syscalls are still not implemented.
My own makeshift OS has a different syscall mechanism, ironically using
the same registers, but a syscall number of -1 (Linux uses positive
syscall numbers).
They work in different ways, IIRC:
X10..X15: Arg1..Arg6
X16: Unused, 0
X17: Syscall Number (always positive)
In my case, syscalls took a different form, IIRC:
X10: Object ID (Handle)
X11: Method Number (Integer)
X12: Method Args List (Pointer)
X13: Return Value (Pointer)
X14..X16: Unused, 0 (RV)
X17: Holds -1 (RV).
In this case, system calls and many OS APIs take the form of object
method calls, with a special range of low-numbered object IDs (Eg, 0 or
NULL) mapping to core/basic syscalls.
But, yeah, some OS APIs would take the form of objects which would be
wrapped in a VTable struct, say:
SomeApi_Vt **api;
(*Api)->ApiMethod(api, arg1, arg2);
In this case, well, there were two major ways of requesting APIs:
Pairs of EIGHTCC values, for some public APIs
Or as FOURCC's for shorthand (zero padded to 64 bits).
As a UUID / GUID:
Primarily used for local / private interfaces.
Well, people probably can't guess where this mechanism originally came
from...
Well, not exactly the same as the inspiration, as there is no IDL
compiler involved, mostly just bare C structs representing the VTables.
There is essentially a blob of generic reusable method-wrappers (and a
whole generic reusable VTable) that is shared across many of these
objects, so calling a method on an object then just sorta translates it
into the corresponding system call to invoke that method slot.
Well, and this mechanism being part of why (for RV) I stuck with an ABI
variant that passes everything in X registers (separate X and F
registers would make a big ugly mess for this whenever a method has a
floating-point argument).
>>
>> Neither is needed with my own compiler, which compiles things in a way
>> such that it eliminates anything that is unreachable.
>
> [...]
>
>>>
>>> That might be the case for a very simplistic compiler. With an
>>> optimising compiler, these extra variables will quickly be
>>> eliminated. If the compiler has a good scheduling model of the
>>> device, it do whatever instruction scheduling works best for that
>>> processor. If the model is not good enough, it will be suboptimal.
>>> I would not, however, expect any different in the generated code for
>>> the two code snippets.
>>>
>>> Sometimes this kind of "manual optimisation" is helpful when you have
>>> to try to get efficient results from a weak compiler, however.
>>>
>>
>> Possibly, but this sort of thing can help with both BGBCC and with
>> MSVC IME
>
> I don't tend to think of MSVC as a highly optimising compiler - but it
> is not a tool I have much use for, as it does not handle the targets I
> need. When I have sometimes looked at the generated code on godbolt, it
> has not impressed me at all. So it could well fall into the "helpful
> when using a weaker compiler" category.
>
Depends on what target I am building for:
Windows Native: Typically MSVC
WSL: Usually GCC or Clang
Seems to have: GCC 13.2.0; Clang 18.1.3
RISC-V GCC: Also 13.2.0 (also via WSL)
Linux: Typically GCC
I rarely much use Cygwin anymore, as it was mostly rendered obsolete by
WSL (on Win10 or similar).
Though, Cygwin may still be relevant on Win7 or WinXP systems.
For BGBCC, it can build both on native Windows and on Linux/WSL (though
recently noted that this build was broken, mostly by GCC and Clang being
more pedantic about missing prototypes, and a few prototypes were being
missed by my function-prototype mining tool). Went and fixed this, but
haven't posted this yet.
As for optimizing in MSVC, yeah, it is in the area of not terrible, but
not super clever either.
If one expects the sort of high-level code-rewriting cleverness that GCC
or Clang often does, one will be disappointed.
But, sometimes, the main "heavy hitter" optimizations are things like
constant-folding and register allocation, which it does do effectively.
Though, both MSVC and BGBCC seem to use one sort of strategy for
register allocation:
Static assign things to callee-save registers and use remaining
registers for dynamic allocation within basic-blocks. Variables with
finite non-overlapping lifetimes (that do not cross basic-block
boundaries) may potentially share a register (this more generally
applies to things like temporaries).
And, GCC and Clang use another: Assign dynamically but carry values
across basic-block boundaries along control-flow paths.
Both tend to give different patterns though, and seem to favor different
types of code.
>>
>>>
>>>>
>>>>>>
>>>>>> Usual strategy is to try to limit how much code is written, and
>>>>>> also to avoid doing things in ways that result in too much code,
>>>>>> or too much cruft.
>>>>>>
>>>>>> Best to avoid both copy paste when reasonable, and sticking
>>>>>> anything non-trivial in macros.
>>>>>
>>>>> We avoided macros if possible.
>>>>>
>>>>
>>>> They are de-facto for constants and similar, but for longer stuff is
>>>> better avoided.
>>>
>>> Macros are rarely the best way to define constants. They are needed
>>> if you are using the constants for pre-processor stuff like
>>> conditional compilation. But generally you get clearer code, better
>>> typing, and potentially several other benefits from using alternative
>>> choices like "enum" (even for stand-alone integer constants), "static
>>> const" variables, and in C23, "constexpr" variables. There's no
>>> doubt that a lot of code /does/ use macros for constants, but I view
>>> it as a relic of the past rather than good coding practice.
>>>
>>
>> They are traditional...
>>
>> Like:
>> static const double M_PI = 3.14159265358979;
>>
>> Could also make sense, but people don't do usually this, they usually
>> use macros...
>
> They should not do so (IMHO, of course). Yes, macros are traditional -
> but there are no plus sides to using them for this kind of thing. (There
> are no plus sides to using all-caps either, but people do that too.)
>
It is more tradition...
My conventions, as noted, are sorta like:
Macros / Constants: All caps;
Functions:
LIBNAME_SysSys_FirstLetterCaps //externally callable within LIBNAME
libname_subsys_nocaps //usually private to a subsystem
LIBNAME_FirstLetterCaps //main API for a private library
somefunction //C library convention
libname_somefunction //some OS API stuff
libFirstLetterCaps //GL-like, common for public APIs
FirstLetterCaps //was common in Win32 API, unused
Conventions are looser for standalone programs, but:
somename, some_name, ... //small programs
S_SomeFunc //id Software like, letter for major subsystem
In my own makeshift OS, had used OpenGL like naming for a lot of OS APIs.
tkWhatever //TestKern OS APIs
tkgdiWhatever //TKGDI: Basically Graphics/GUI stuff
As noted, some amount of these are implemented as object wrappers.
Likewise for my OpenGL implementation.
Though, OpenGL is more annoying in that it usually works via a
"GetProcAddress()" type mechanism, so you need to fetch each function
pointer internally (and provide a lookup mechanism for each function).
Where, the main (static linked) part of the GL API is effectively
wrapper functions over function pointers gained via said
"GetProcAddress()" mechanism, which then go into the userland
implementation of those functions (typically, with part of the GL API
running in userland, and a backend part that runs "elsewhere", such as
in the GUI process, and is reached over an Object / COM interface).
FWIW, I didn't design this part of the GL API, but if I had, probably
would have just used COM objects internally.
Still better IMO to provide a nice C API wrapper over said COM objects
though, rather than go the DirectX route and be like "Hey, application
code, have fun with these here bare COM objects!".
Exposing bare COM objects and GUIDs in a public API is poor design IMO.
Well, even if in effect many of the API calls are just:
void apiDoSomething()
{ (*someapi_context)->DoSomething(someapi_context); }
This differs some from Linux APIs, which often like sharing bare
functions and variables across API boundaries (so, no real wall of
separation between the library and application in this sense).
These partly runs into an issue in that in my case, BGBCC (like MSVC)
requires being explicit about DLL imports and exports, and sharing
global variables across DLL boundaries is generally discouraged.
Note that the DLL mechanism doesn't actually support sharing global
variables directly, so if you try to share a global across a DLL
boundary, what you actually get is a hidden function-call that returns a
pointer to the variable.
__declspec(dllimport) int somevar; //not actually a variable.
x=somevar;
Is more like:
x=*(int *)(__get_somevar());
But, generally discouraged.
Sharing variables across DLLs is bad practice IMO, and ideally only
sharing functions that represent a public API (and not, "whatever random
stuff happens to be in the library"). Contrast to the Linux "shared
object" approach which does tend to take more of a "share everything"
approach, and libraries tend to not maintain as string of a
library/application separation.
Well, and then Cygwin goes and tries to fake Linux behavior on top of
DLLs (in which case a large library can also find itself running into
the hard limit on the maximum number of DLL exports).
...
Can note that I had approached C library linking in a different way from
MSVC/Windows:
Windows:
Main EXE and every DLL get their own static-linked C library.
Can opt into a shared DLL for the C library, but this adds wonk.
BGBCC+TestKern:
Main EXE gets a static-linked C library;
Exports a COM interface that DLLs can use;
DLLs get a static linked C-library stub;
Invokes main C library via a hidden COM interface.
This basically allows things like malloc/free and stdio to work across
DLL boundaries (unlike Windows where each gets their own local heap and
stdio, and trying to invoke a pointer from one DLL in another tends to
cause stuff to explode).
Granted, the DLLs effectively pulling the C library from the main EXE
via COM objects may seem a little unorthodox, but it seemed like the
best way to address my use cases.
> (I'm snipping all the details of your own C compiler, because there is
> very little I can comment on.)
>
>>
>>>>
>>>>
>>>> But, things can be considered in relative terms:
>>>> Like, C++ may carry various penalties vs C.
>>>>
>>>
>>> I don't find C++ carries noticeably penalties compared to C, for my
>>> embedded work. But I do disable exceptions and RTTI - exceptions may
>>> have very little run-time time overhead, but the unwind tables can be
>>> significant when code size is important in small systems.
>>>
>>
>> Yes, that is the main thing.
>> They carry zero performance penalty in practice;
>> But, have a non-zero penalty for image size.
>>
>> Not enough to be a deal-breaker towards using them if they are used,
>> but enough that one wants them disabled if not used...
>>
>
> Agreed.
>
> (I could also note that I make heavy use of templates in C++ code - it
> often leads to smaller and faster results.)
>
Curious...
I had tended to use the "write everything one off for the task at hand"
approach, but this is a higher-effort approach.
...
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2026-05-31 11:14 +0200 |
| Message-ID | <10vgu5m$1e9l1$1@dont-email.me> |
| In reply to | #399540 |
On 30/05/2026 22:48, BGB wrote:
> On 5/30/2026 6:52 AM, David Brown wrote:
>> On 29/05/2026 22:16, BGB wrote:
>>> On 5/29/2026 6:22 AM, David Brown wrote:
>>>> On 29/05/2026 12:20, BGB wrote:
>>>>> On 5/29/2026 2:52 AM, Janis Papanagnou wrote:
>>>>>> On 2026-05-28 11:57, BGB wrote:
>>>>>>> On 5/28/2026 2:18 AM, Janis Papanagnou wrote:
>>>>>>>> On 2026-05-28 01:49, BGB wrote:
>>>>>> [...]
>>>>
>>>>>>>
>>>>>>> But, not really an "easy" way to avoid bloat, other than to write
>>>>>>> code specifically for what cases are relevant; while also
>>>>>>> avoiding needless duplication and copy paste (where, overuse of
>>>>>>> copy/paste can also lead to bloat; along with turning the code
>>>>>>> into an ugly mess).
>>>>>>
>>>>>> Hmm.. - as said, the during very early days there were issues; I
>>>>>> recall on one platform duplication of template code in more that
>>>>>> one source unit. And/or some environmental hacks (of the compiler)
>>>>>> to deposit template code for linking. In the later days I've not
>>>>>> seen such immature things anymore.
>>>>>>
>>>>>
>>>>> Possibly, a lot could depend on how one is counting things as well.
>>>>>
>>>>>
>>>>> In a lot of cases when using GCC, I end up using:
>>>>> -ffunction-sections -fdata-sections -Wl,-gc-sections
>>>>
>>>> On many targets, "-fdata-sections" can lead to noticeably larger and
>>>> slower code because it effectively eliminates section anchor
>>>> optimisations. It does not negatively affect x86 AFAICS, because
>>>> x86 does not use section anchors.
>>>>
>>>> <https://godbolt.org/z/zeoq41Y7d>
>>>>
>>>> With -fsection-anchors (enabled with optimisation on targets that
>>>> support it - generally RISCy load/store architectures), program-
>>>> lifetime variables are kept together in a lump (as though they were
>>>> in a struct) and often addressed by a pointer to that pretend
>>>> struct. Thus if a function accesses two variables "a" and "b",
>>>> instead of having to load the addresses of each of "a" and "b" into
>>>> separate registers, it loads an "anchor" into one register and
>>>> accesses the variables with reg+offset addressing.
>>>>
>>>> I've seen "-fdata-sections" used regularly in embedded systems - it
>>>> is almost always a bad idea.
>>>>
>>>> ("-ffunction-sections" is often very helpful to reduce code image
>>>> size, so keep that one.)
>>>>
>>>
>>> Both seem to help on x86, x86-64, and also on RISC-V, at making GCC's
>>> output at least sorta space-comparable to my own compilers.
>>>
>>> The merit of "-fdata-sections" is mostly that it eliminates unused
>>> global variables; whereas "-ffunction-sections" eliminates
>>> unreachable functions.
>>
>> That is the point of them, yes. "-ffunction-sections" can be useful
>> at removing unused code from more general code. For microcontrollers,
>> SDK's and manufacturers' driver code will normally contain a large
>> number of functions that can be eliminated in this way, saving a lot
>> of code space.
>>
>> However, in practice, "-fdata-sections" rarely eliminates a
>> significant amount - most programs do not have large amounts of
>> statically-allocated data that is not used. Gcc, and I think most
>> other compilers, put the static lifetime data for each translation
>> unit in its own section, so if no data from a translation unit is used
>> it will be eliminated at link time even with -fno-data-sections. And
>> of course it makes no difference for heap data or stack data.
>>
>
> The main place it makes a difference is global arrays from a translation
> unit that is included, but for functions that are not included.
>
> Also functions with large static arrays.
>
>
> void SomeFunc()
> {
> static char buf[4096];
> ...
> }
>
> Where, say, eliminating SomeFunc does not necessarily eliminate buf.
Yes, if you have such code but want to eliminate it, then
-fdata-sections would definitely benefit. I have not seen such code in
practice (at least not with very big static arrays, and that also was
not an essential part of the program). But of course I have only seen a
microscopic part of all C code written - if you come across this sort of
thing, then I appreciate your point.
(There are several ways to make this more "friendly" to builds that need
to be compact, such as putting the buffer and/or SomeFunc in a separate
file or giving it a specific section of its own.)
>
>
>> In my testing, "-ffunction-sections" is absolutely worth using (on
>> targets where code space is relevant - there's no need for PC
>> software). On some targets, it may mean a few lost opportunities for
>> shorter jump/call instructions between functions in the same
>> translation unit, but the cost is rarely anything more than a slightly
>> longer link time. But "-fdata-sections" typically gives almost no ram
>> space savings, and makes code bigger and slower.
>>
>> As I noted, gcc on x86 does not support section anchors, so there is
>> not likely to be much code cost for -ffdata-sections.
>>
>> Where section anchors shine - and where -fdata-sections therefore has
>> cost - is when a function needs to access more than one piece of
>> static lifetime data defined in the same translation unit (or another
>> translation unit if you are using LTO). That happens a lot in
>> embedded ARM programming at least. I don't know about RISC-V. If the
>> target normally uses a "small data section" for ram (I know this is
>> common on PowerPC), then there is, in effect, a program-wide section
>> anchor already. So it is possible that it relatively few targets have
>> section anchors - but the 32-bit ARM on gcc is a vastly popular choice
>> in the embedded world, so it is important to understand the cost of
>> this compiler flag for that target at least.
>>
>
> It depends on the way it is built.
>
>
> A lot of times though (for non-relocatable static-linked binaries) it
> mostly tends to use AUIPC+LD or AUIPC+ST pairs to access global
> variables. There is a Global Pointer that needs to be loaded when the
> binary is started, unclear what it is used for exactly.
>
If you have a global pointer, then it will probably be used for
gp+offset access to global data, eliminating the need for section anchors.
I have not used RISC-V, and am not familiar with its details. I can see
from godbolt that when -fdata-sections is in action and you are loading
from static lifetime variables, the compiler generates instructions like
lw a5, a_variable
lw a4, b_variable
lw a0, c_variable
When you do not have "-fdata-sections", it uses anchors :
lla a4, .LANCHOR0
lw a5, 0(a4)
lw a3, 4(a4)
lw a0, 8(a4)
From my (limited) understanding, RISC-V cannot use 32-bit absolute
addressing. So the "lw a5, a_variable" must be a pseudo-instruction -
using register + offset addressing. If there is a global pointer, then
presumably that is used here. Alternatively, the pseudo instruction
might assemble to two real instruction to support the 32-bit address. I
know both techniques are used in some targets, but don't know about RISC-V.
Certainly it would surprise me if the "lw a5, a_variable" version were
more efficient than using anchors - otherwise why would gcc generate
code with anchors when given a free choice? (Perhaps gcc is not well
tuned for RISC-V code generation - I am wary of making too many
assumptions about the processor just from some simple compiler outputs.)
(clang does not, apparently, support section anchors as an optimisation
technique. Both with and without -fdata-sections, on RISC-V it first
uses two instructions to load ".L_MergedGlobals" into a register and
then uses that register plus offset to access data.)
>>
>> I don't tend to think of MSVC as a highly optimising compiler - but it
>> is not a tool I have much use for, as it does not handle the targets I
>> need. When I have sometimes looked at the generated code on godbolt,
>> it has not impressed me at all. So it could well fall into the
>> "helpful when using a weaker compiler" category.
>>
>
> Depends on what target I am building for:
> Windows Native: Typically MSVC
> WSL: Usually GCC or Clang
> Seems to have: GCC 13.2.0; Clang 18.1.3
> RISC-V GCC: Also 13.2.0 (also via WSL)
> Linux: Typically GCC
>
> I rarely much use Cygwin anymore, as it was mostly rendered obsolete by
> WSL (on Win10 or similar).
> Though, Cygwin may still be relevant on Win7 or WinXP systems.
>
Cygwin has its own wide range of complications. If you want to use gcc
targeting native Windows, msys2 and mingw-64 are probably your best bet,
either compiled natively under msys2 or as a cross-compile from Linux.
But don't place too much emphasis on my advice, as I very rarely compile
C or C++ code for Windows - most of my PC target (Linux or Windows)
coding is in Python.
> For BGBCC, it can build both on native Windows and on Linux/WSL (though
> recently noted that this build was broken, mostly by GCC and Clang being
> more pedantic about missing prototypes, and a few prototypes were being
> missed by my function-prototype mining tool). Went and fixed this, but
> haven't posted this yet.
>
>
> As for optimizing in MSVC, yeah, it is in the area of not terrible, but
> not super clever either.
>
> If one expects the sort of high-level code-rewriting cleverness that GCC
> or Clang often does, one will be disappointed.
>
> But, sometimes, the main "heavy hitter" optimizations are things like
> constant-folding and register allocation, which it does do effectively.
>
> Though, both MSVC and BGBCC seem to use one sort of strategy for
> register allocation:
>
>
> Static assign things to callee-save registers and use remaining
> registers for dynamic allocation within basic-blocks. Variables with
> finite non-overlapping lifetimes (that do not cross basic-block
> boundaries) may potentially share a register (this more generally
> applies to things like temporaries).
>
> And, GCC and Clang use another: Assign dynamically but carry values
> across basic-block boundaries along control-flow paths.
>
> Both tend to give different patterns though, and seem to favor different
> types of code.
>
[...]
>>
>> (I could also note that I make heavy use of templates in C++ code - it
>> often leads to smaller and faster results.)
>>
> Curious...
>
>
> I had tended to use the "write everything one off for the task at hand"
> approach, but this is a higher-effort approach.
>
A lot of code tends to fall into the category of shuffling data around
or doing simple checks or conversions. It's also common to have wrapper
functions for libraries to get something nicer, safer and more
convenient than some API that belongs in the early 1990's. Good C++
templates (and sometimes even good macros in C) can make the use of
these things far nicer, and most of the code that the templates appear
to generate inline in the caller disappears in optimisation.
[toc] | [prev] | [next] | [standalone]
Page 1 of 14 [1] 2 3 … 14 Next page →
Back to top | Article view | comp.lang.c
csiph-web