C23 - What We Have To Suffer
Written by Harry Fairhead   
Wednesday, 05 April 2023

It is a long-standing mystery to me that the people who standardize C really don't seem to use it much, or if they do it is in some refined academic way that is purely for amusement. The latest C standard, C23 is due later in the year and it isn't good.

Ccoverdetail

I've been using C for low-level programming throughout most of its standards and for most of the time I have upgraded to the next standard reluctantly. I suppose I'm not as bad as Linus Torvalds and Linux which until recently was stuck on C89 and is now in the process of moving to C11. The best that can be said for C11 is that it didn't break much if you selected the right options. Personally C99 was my choice rather than C11, but there isn't a lot in it. 

Now we have the latest attempt to ruin a perfectly good language - C23, shame it wasn't last year as that would have allowed C(atch) 22 jokes. As far as I can tell, things started to go wrong when the idea of "undefined behavior" was introduced, not as a problem but as a way of allowing compiler writers to resort to optimizations that are simply barbaric in any reasonable programmer's opinion. I still fume daily at the optimization that changes:

printf("start");
for(i int,i=0,i++){}
printf("end");

into

printf("start");
printf("end");

An optimization is supposed to never change the action of a program, but clearly C compiler writers have no sense of time. 

It is examples like this that indicate that the people in control of C aren't the people who use C. If they were, undefined behavior would be minimized and optimizations wouldn't change the action of a program.

Let me turn to something nice about C23. We now have checked arithmetic. 

bool ckd_add(type1 *result, type2 a, type3 b);
bool ckd_sub(type1 *result, type2 a, type3 b);
bool ckd_mul(type1 *result, type2 a, type3 b);

The idea is that the functions return false if the arithmetic worked out such that the operation between type2 and type3 produces something that can be represented in type1 without error. If the function returns true then this is not the case and the  result is what you would get using unsigned arithmetic and truncating the result. Notice that now two's complement arithmetic is the standard. This is also what you would automatically get on the most common hardware without the functions. The only thing we have extra is the overflow detection. Of course, you can't use these functions for compile-time arithmetic and they don't make expressions easy. I think there are probably better ways of doing the same job.

Now we come to the lunacy of "unreachable". You can mark a code path as unreachable and the compiler will remove it for you. The annotation is intended to allow you to inform the compiler that, to the best of your knowledge, the path cannot be reached. For example:

if(condition){
   unreachable();
   code
}else{
  code
}

Why? Why would I ever want to mark a path as unreachable!
I want the compiler to warn me when a path is unreachable, not the other way round. There are also cases where the compiler will remove the unreachable code and code associated with it that isn't marked as unreachable. This is a very dangerous and, as far as I can see, completely unnecessary addition.

Another big problem is the changed behavior of realloc. There are some subtleties here but the big problem is that at the moment:

p=realloc(p,0);

returns a NULL and frees the memory. This seems reasonable as resizing an allocation to zero should free the memory, i.e. be identical to free(p). The new C23 standard has changed this reasonable and useful behavior to be undefined behavior!!
As if we weren't already suffering enough from undefined behavior! This will break many existing programs and cause problems for new code for no good reason. 

I was in the middle of writing this complaint when I encountered another and very readable account of the same problem:

Catch-23: The New C Standard Sets the World on Fire

After reading it I can't do any better. So simply stop reading my rant at this point and read it, and then come back for a conclusion.

As I suggested at the start, the problem seems to be that the people in charge of the standards seem to think that C is a high-level language that should morph into Java, or worse Haskell or even worse C++. As it happens, C23 increases the split between C and C++ and C23 can no longer be regarded as subset of C++. 

The world has lots of high-level abstract languages. C is about bit patterns and representations, not abstract types. It is time to take back control and make C a machine-independent assembler and use this definition to banish all undefined behavior into implementation-dependent behavior. 

operators

 

More Information

Catch-23: The New C Standard Sets the World on Fire Terence Kelly with Special Guest Borer Yekai Pan

C23  N3096

Related Articles

Linux To Move To C11

C Is Number One Language Again

C Undefined Behavior - Depressing and Terrifying (Updated)

GCC Gets An Award From ACM And A Blast From Linus        

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

 

Banner


52nd Mersenne Prime Found
27/10/2024

It has been nearly six years since the last Mersenne prime was discovered. Now, at last, we have Mersenne prime number 52 and it has 41,024,320 digits!



TypeScript Improves Never-Initialized Variables Checks
21/10/2024

Microsoft has announced TypeScript 5.7 in beta, with improvements including stronger checks for variables that have never been initialized before use, and path rewriting for relative paths.


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info

 

<ASIN:1871962609>

<ASIN:1871962617>

<ASIN:1871962633>

<ASIN:187196279X>

Last Updated ( Wednesday, 06 November 2024 )