Re: On C99, C11, and other dialects

Steffen Nurpmeso <[email protected]>
Newsgroups gmane.mail.mutt.devel
Message-ID <20260422144300.yEv7gpnz@steffen%sdaoden.eu>
Hello Alejandro.

Alejandro Colomar via Mutt-dev wrote in
 <aefqanH_-tiRgHxI@devuan>:
 |On 2026-04-21T16:55:51+0200, Steffen Nurpmeso wrote:
 |[...]
 |> No no, it was broken.  It could not evaluate the same expressions
 |> as the C++ variant could.  Maybe it was a compiler error, then.
 |> Note the IANA TZ project also did it like so:
 |> 
 |>     * private.h (static_assert): New macro, defined for pre-C23 compilers\
 ...
 |>   +#if __STDC_VERSION__ < 202311
 |>   +# define static_assert(cond) extern int static_assert_check[(cond) \
 |>   ? 1 : -1]
 |>   +#endif
 |> 
 |> (I am now not reading exact ISO C definitions to find reasons why
 |> the C11 variant was borked.  But it was once i tested.)
 |
 |Ahhh, now I see what your problem was.  The problem wasn't
 |static_assert(3) in C.  The problem was that integer constant
 |expressions were significantly more strict in C11, and C23 has allowed
 |compilers to turn some code into constant expressions in certain cases.
 |
 |I guess this is another good reason to use C23.

Or you use C89/C++98 with the simple pseudo typedef that i (and
many other people with similar ones) use for static assertions
for many many years, eg

  # define su_CTA(T,M) su__CTA_1(T, su_FILE, __LINE__)
  # define su_LCTA(T,M) su__LCTA_1(T, su_FILE, __LINE__)
  
  # define su__CTA_1(T,F,L) su__CTA_2(T, F, L)
  # define su__CTA_2(T,F,L) typedef char ASSERTION_failed_file_ ## F ## _line_ ## L[(T) ? 1 : -1]
  # define su__LCTA_1(T,F,L) su__LCTA_2(T, F, L)
  # define su__LCTA_2(T,F,L) \
  do{\
          typedef char ASSERT_failed_file_ ## F ## _line_ ## L[(T) ? 1 : -1];\
          ASSERT_failed_file_ ## F ## _line_ ## L su____i_am_unused__;\
          su_UNUSED(su____i_am_unused__);\
  }while(0)

Yes i use static_assert() in C23+.  But i actually see no
improvement (there is actually none for me, the above "just works"
(tm)), *and* i am in doubt, because ISO C11 was unusable, C17
was unusable, but with C23 it now works.  It should never have
entered the standard until it was usable.  I am not sitting in
an almost 700 page standard (C-2011) with its "1000" undefined or
incompletely defined or so conditions, nor am i keen for this.
This is in parts where Mr. Ken Thompson picked me up.

 ...
 |>|that the macro expands internally T*, which would expand as int[4]*,
 |>|which is a syntax error.  But with typeof(), you have typeof(int[4])*,
 |>|which is correct.
 |> 
 |> I btw still prefer typedef for for example the handler (and
 |> anything prototype-ish) of signal(3) and such.  I just seem to be
 |> incapable to perform proper views at this otherwise (like the
 |> prototype shown in "man 3 signal" on Linux).
 |
 |There's signal(3posix) and signal(2).  There's no signal(3) --although
 |if you run `man 3 signal`, you'll get signal(3posix)--.
 |
 |Here's the SYNOPSIS from POSIX:
 ...
 |      void (*signal(int sig, void (*func)(int)))(int);
 |
 |And here's the one from the Linux man-pages project:
 |
 | SYNOPSIS
 |      #include <signal.h>
 |
 |      typedef typeof(void (int))  *sighandler_t;
 |
 |      sighandler_t signal(int signum, sighandler_t handler);
 |
 |The latter still uses typeof() --even if it also uses typedef-- for
 |reasons similar to malloc_T().  If we didn't use typeof() in that
 |typedef definition, it would become quite unreadable.

I have a hard time even understanding the above.  void(int), that
is a nerd horror show.  :-)

 |[...]
 |> I meant "warnings yes, but no errors".  It is sometimes at least
 |> hard enough to see the "xy is reported only once" for some
 |> warnings.  I let the compilation go one, and then crawl the (tmux;
 |> or output redirection, or what) history along.
 |> I mean sure, if you have a plethora of builds and only get
 |> a notification email, having hard errors seems the better way.
 |> But i only develop locally, and have some (by far not enough, and
 |> most younger than 2022) VMs.
 |
 |Since make(1) builds step by step, I don't see a problem in building
 |until the first error, fix a few things, and then continue the build,
 |until everything works.  I don't like navigating a sea of warnings.

Make step-by-step?  How that?  But i can hardly believe a big
project can do it like that, say a Linux kernel build?

 |>|>|If you write this malloc_T() in a library once, and then use it
 |>|>|everywhere, you shouldn't worry too much about it having too much
 |>|>|typeof magic.
 |>|> 
 |>|> Yes.  Kernel, too, and i had just seen the commit that made it
 |>|> simpler to use for the generic "bin".  (By sheer chance.)
 |>|
 |>|That commit from Torvalds was horrible.
 |>|That macro is a massive foot-gun.
 |>|<https://lore.kernel.org/lkml/abhGS0n_RsUG97Ni@devuan/>.
 |> 
 |> I remembered now that i came via
 |>   https://lwn.net/Articles/1057769/
 |> to
 |>   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm\
 |>   it/?id=bdc5071d7f7b
 |> and especially
 |>   https://lwn.net/Articles/1058664/
 |> pointed to several fixes of that, like
 |>   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm\
 |>   it/?id=e19e1b480ac7
 |> In this hindsight it seems hard to understand that making it
 |> "completely cool" aka "fool proof" was not an option.
 |
 |I think it's a combination of
 |
 |-  They didn't realize it would be so dangerous.
 |-  Lack of communication.
 |
 |I'm more concerned about the fact that it hasn't been fixed.  And I'm
 |even more worried by the fact that the kernel-hardening maintainer is
 |worried of annoying Torvalds with a fix, so they prefer not fixing it at
 |all.  That doesn't seem healthy.
 |
 |> (*But*, then again, i remember compiler errors with MACRO(x,y,)
 |> syntax, and i even remember being surprised a couple of years ago
 |> that MACRO(x,y, ), ie with space, worked!
 |
 |Could you please point to those?  I'd be interested in investigating
 |that.  I don't see reasons why that should be any different.  I'd like
 |to see a small reproducer piece of code.

Only just like i said.  (Ie, some macro with (xy,) and one with
(xy, ).)  But no, i cannot, other than that.  I think we are, at
least in parts, talking times when there was not even __VA_ARGS__,
widely spread at least; we did not use such preprocessor things
until .. actually i am still very careful with that, my pam_xdg.c
(that is *mine*, not the other one(s)) for example still says

  pam_xdg.c: *@ - Requires C preprocessor with __VA_ARGS__ support!

and that is hammer!, you know -- even va_list was not everywhere
at times, at least potentially!

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.