All chapters of the C23 edition of Modern C now available in early access

At the same time as WG14 (the C committee) voted C23, now all 21 sections of the new edition are available via Manning’s early access program on

Modern C, Third Edition — Covers the C23 standard

This new edition broadly covers all the novelties that will come with C23, many of them make coding in C easier and more reliable. It’s worth a look. Major public domain compilers such as gcc and clang are getting ready to support most of this in their next releases, so you on many platforms you will be able to use these new features right away.

Some pieces are still missing though, namely some of the C library support. Therefor the part in the appendix for C23 about just that is not yet ready, but we will be getting there soon.

You might be interested in the special code that you can get on

Modern C — web page

and the previous post that described the whole

Early access to the C23 edition of Modern C

White space does matter in C23

Usually in C identifiers are not directly followed by strings. But when U prefixed literals were introduced in C. there still were some rare clashes with existing code. This happened were a macro U that expanded to a string was used to add some sort of leading character sequence to a string. Prior, this usage was not sensible to whether or not there was a space between the two. By introducing the prefix the two usages (with and without space) became distinct and code changed its meaning or became invalid. So for this situation, space is in fact already significant.

Generally, it is often assumed that in C spaces don’t contribute much to the interpretation of programming text, but for C23 this has become an over-simplification that does not reflect the situation anymore.

In addition to problems internal to C, there is a problem of interfacing with C++, where some of the rules are different.

syntax meaning, C23 different meaning, C++
# define X(A) function like macro, empty
# define X (A) object macro, expands to (A)
0x4'7'a hex number with digit separators
0x4 '7'a number, character literal, and identifier number, character literal with suffix
0x4 '7' a number, character literal, and identifier
"%" PRIx64 valid format string for printf
"%"PRIx64 valid format string for printf string literal with suffix
R "(hör)" identifier followed by multi-byte string
R"(hör)" identifier followed by multi-byte string raw multi-byte string, contains just hör
R "hör" identifier followed by multi-byte string
R"hör" identifier followed by multi-byte string invalid raw string
U "hör" identifier, followed by multi-byte string
U"hör" UTF-32 string

It would be good if there could be some coordination here between C and C++ about such simple questions concerning lexing and the preprocessor.

Any use of identifiers that are adjacent to character and string literals should be discouraged; I think that such constructs should just be excluded by the syntax. If we want this to be diagnosed it should be before compilation phase 4, in particular before macro expansion. Best would be if this is diagnosed in phase 3, lexing.

Compilers and preprocessor implementations could start to warn about such possible collision immediately, as of today. I don’t see much of a reason to still allow it. Even where there are valid uses, such as for the printf format string macros, the code becomes much easier to read if these are separated from the surrounding format string.

The deprecated attribute in C23 does much more than marking obsolescence

You may already have heard that C23 proposes a new syntax feature called attributes and that one of the standard attributes in C23 is called deprecated. Actually, we got this whole attribute thing and also some of the standard attributes from C++, where they had been introduced in C++11 (I think). One of the uses of this particular attribute is to mark a given feature as obsolescent. For example in C23 we now have

[[deprecated]] char* asctime(const struct tm* timeptr);
[[deprecated]] char* ctime(const time_t* timer);

This simply says that user code should not use these functions anymore, and that compilers should issue a diagnostic if they do.

But this is only one of the possible uses of this new feature. First of all, it can be placed on very different kinds of features, functions, types, variables, enumeration members, structure members …

But most importantly it can be put on features that you somehow have to expose in a header, but which are really only part of the internal dealings of your code, something that users just shouldn’t touch because the feature needs careful maintenance or that simply might change in the future.

In the C23 edition of Modern C, see this post, I just modified a detailed example to use this new feature:

typedef struct circular circular;
struct circular {
  size_t  start [[deprecated("privat")]]; /* First element     */
  size_t  len   [[deprecated("privat")]]; /* Number of elements*/
  size_t  cap   [[deprecated("privat")]]; /* Maximum capacity  */
  double* tab   [[deprecated("privat")]]; /* Data array        */
};

What you see here, is a structure type that can be used by application code: variables can be declared, the size is known. But none of the members of the structure can be accessed directly without being warned.

Continue reading “The deprecated attribute in C23 does much more than marking obsolescence”

Early access to the C23 edition of Modern C

Manning’s early access program (MEAP) for the new edition is now open
at

https://www.manning.com/books/modern-c-third-edition

There is a special code mlgustedt2 to get 45% off of the official price. This is currently limited until Jan 31.

The previous edition already has been largely successful and is considered by some as one of the reference books on C. This new edition has been the occasion to overhaul the presentation in many places, but its main purpose is the update to the new C standard, C23. The goal is to publish this new edition of Modern C at the same time as the new C standard goes through the procedure of ISO publication and as new releases of major compilers will implement all the new features that it brings.

Among the most noticeable changes and additions that we handle are those for integers: there are new bit-precise types coined _BitInt(N), new C library headers (for arithmetic with overflow check) and (for bit manipulation), possibilities for 128 bit types on modern architectures, and substantial improvements for enumeration types. Other new concepts in C23 include a nullptr constant and its underlying type, syntactic annotation with attributes, more tools for type generic programming such as type inference with auto and typeof, default initialization with {}, even for variable length arrays, and constexpr for name constants of any type. Furthermore, new material has been added, discussing compound expressions and lambdas, so-called “internationalization”, a comprehensive approach for program failure.

During MEAP we will also add an appendix and continue work on a temporary include header for an easy transition to C23 on existing platforms, that will allow you to start off with C23 right away.

We also encourage you to post any questions or comments you have about the content in the liveBook Discussion forum. We appreciate knowing where we can make improvements and increase your understanding of the material.

Note that the “about this book” section in MEAP is a bit hidden under the front page. I think that reading this even before going in details is important so I repeat some of this information here.

Continue reading “Early access to the C23 edition of Modern C”

The new __VA_OPT__ feature in C23

C23 brings a new macro feature that eases programming with variadic macros a lot. Before it has been a challenge to detect if a ... argument was actually empty or contained at least one real token. This feature was introduced into C23 by a paper by Thomas Köppe “Comma omission and comma deletion” A similar feature had already been integrated to C++20 before.

As an example for the feature, suppose we want to augment calls to fprintf such that two types of problems are detected:

  1. If there is only a format argument and no others, we want to use fputs to avoid scanning the format at execution time.
  2. If there are more than one arguments, it should be assured that the format is a string literal, such that the contents can be parsed at compile time.
Continue reading “The new __VA_OPT__ feature in C23”

Enforced bounds checking for frozen function interfaces

Many functions in the C library and other legacy codes have interfaces that don’t permit the current bounds checking syntax for array parameters, but that are frozen in time such that nobody will ever be able to change and improve them. In this example we go with

void* memcpy(void*restrict s1, void const*restrict s2, size_t n);

but in fact any existing interface that has size parameters after array or pointer parameters that depend on them has similar problems. The intent of this post is to show how the corresponding header can be easily tuned, such that modern compilers are able to provide static analysis that diagnoses calls that receive buffers that are too small compared to n. The trick to do so is just a two-level wrapper that interchanges call arguments, nothing very deep, and not something that compilers wouldn’t be able to perform if we just had means to specify this property in the language.

Continue reading “Enforced bounds checking for frozen function interfaces”

Dealing with overflow

In the previous post we have seen that C23 will provide us with tools for efficient overflow check for arithmetic. When discussing this, several people have asked why these tools do not provide a specific model to handle overflow, such as aborting or raising a signal. The answer to this is actually quite simple:

There is no commonly agreed strategy to handle overflow.

So for the C committee (and for the gcc feature this is based upon) there was no obvious choice for a strategy. Instead, the features provide the basics to implement any such strategy based on policy decisions that will be dependent on application specific settings, be they technical or cultural

Continue reading “Dealing with overflow”

Checked integer arithmetic in the prospect of C23

As you might have noticed, C23 is scheduled to come out in November 2023 and will have a lot of improvements and new features, in particular for integers. One of the most controversial properties of integer arithmetic in C is the overflow behavior. C23 will have a new header <stdckdint.h> for “checked integer operations”, that helps to deal with overflow and puts the responsibility in your hands, the programmer. In addition to the result of an arithmetic operation, the interfaces provide an extra bool value that tells if the operation has been erroneous or not.

The addition that has been integrated into C23 is the core proposal and
some amendments. The history of this looks a bit confusing because later editions of the paper have removed parts that had already been adopted.

Anyhow, for many of you it is even possible to use these features in a C23 compatible way just now, because they are closely modeled after similar gcc and clang features. Since overflow still is an important source of bugs and security issues, you should just

start using checked integer operations, now!

Continue reading “Checked integer arithmetic in the prospect of C23”

C23 implications for C libraries

[Edited after final ballot procedure]

The upcoming standard C23 has a lot of additions to the C library clause. Most of them are small, some of them are big but optional. I have now finished a a document that summarizes many of the changes. It has some general discussions about the following subjects

and then lists changes to individual header files of the C library.

This does not contain an detailed description of the changes to the math.h header. First, I am really not an expert on that, and second the changes there are quite invasive and we don’t have a diff-file that would clearly list them.