§ modern-c-features
NOTE: this is a web “mirror” of Anthony Calandra’s modern-c-features shared under MIT License (see at bottom). The only reason I do a copy is I hate reading markdowns from github. I want something simple and plain for my own reference.
§§ Overview
A collection of descriptions along with examples for C language and library features.
C23 includes the following language features:
- auto
- constexpr
- decimal floating-point types
- bit-width integers
- binary literals
- char8_t
- utf-8 character literals
- unicode string literals
- empty initializer
- attributes
- new keywords (C23)
- nullptr
#embed- enums with underlying type
- typeof
- improved compatibility for tagged types
C23 includes the following library features:
- floating-point formatting functions
- memset_explicit
unreachablemacromemccpystrdupandstrndupgmtime_randlocaltime_rtimespec_getres
C17 contains defect reports and deprecations.
C11 includes the following language features:
- generic selection
- alignof
- alignas
- static_assert
- noreturn
- wide string literals
- anonymous structs and unions
C11 includes the following library features:
- bounds checking
- timespec_get
- aligned_malloc
- char32_t
- char16_t
- <stdatomic.h>
- <threads.h>
- quick exiting
- exclusive mode file opening
§§ C23 Language Features
§§§ auto
auto-typed variables are deduced by the compiler according to the type of their initializer.
|
|
See: generic selection.
§§§ constexpr
Scalars specified with constexpr are constants: they cannot be modified after being initialized, and must be fully initialized to a value that can be stored in the given type.
The C constexpr specifier does not support functions, structures, unions, or arrays. Additionally, constexpr cannot be specified for pointer, atomic, or volatile-qualified types.
|
|
§§§ Decimal floating-point types
Supports IEEE-754 Decimal floating-point types, _Decimal32, _Decimal64, _Decimal128. These floating point types are designed for base-10 floating point semantics.
As of September 2023, compiler support is lacking for most features.
§§§ Bit-width integers
The _BitInt(N) type allows specifying an N bit integer signed or unsigned type.
§§§ Binary literals
Binary literals provide a convenient way to represent a base-2 number. It is possible to separate digits with '.
§§§ char8_t
An unsigned char type for holding 8-bit wide characters.
See: char32_t, char16_t, unicode string literals.
§§§ UTF-8 character literals
A character literal that begins with u8 is a character literal of type char8_t. The value of a UTF-8 character literal is equal to its ISO 10646 code point value.
|
|
See: char8_t, unicode string literals.
§§§ Unicode string literals
String literals prefixed with u8, u, and U represent UTF-8, UTF-16, and UTF-32 strings respectively.
See: char32_t, char16_t, char8_t, wide string literals.
§§§ Empty initializer
An object is empty-initialized if it is explicitly initialized using only a pair of braces. Arrays of unknown size cannot be initialized by an empty initializer. If an object is initialized using an empty initializer, default initialization occurs:
- Pointers are initialized to
NULL; - Decimal floating point types are initialized to positive zero;
- Arithmetic types are initialized to zero;
- Array types are initialized such that each slot is initialized according to these rules;
- Aggregate types are initialized such that each member is initialized according to these rules;
- Unions are initialized such that the first named member is initialized according to these rules.
§§§ Attributes
Attributes provide a universal syntax over __attribute__(...), __declspec, etc. C++-styled attributes.
C23 provides the following attributes:
[[deprecated("reason")]]- the entity declared with the attribute (such as a function), is deprecated. Specifying a reason is optional and can be ommitted.[[fallthrough]]- indicates falling-through in a switch statement case is intentional.[[nodiscard("reason")]]- encourages a compiler warning if the return value for the function declared with this attribute is discarded. Specifying a reason is optional and can be omitted.[[maybe_unused]]- suppresses a compiler warning on the entity where this attribute is declared if it’s unused (such as an unused function parameter), if applicable.[[noreturn]]- indicates that the function this attribute is declared on does not return.- Compiler-specific directives - such as
[[clang::no_sanitize]].
See: noreturn.
§§§ New keywords (C23)
New keywords replacing traditional macros definitions:
trueandfalsethread_localstatic_assert
See: static_assert.
§§§ nullptr
Introduces a new null pointer type designed to replace NULL. nullptr itself is of type nullptr_t which can be implicitly converted into pointer types and bool, and – unlike NULL – is not convertible to integral types.
§§§
#embed
#embed is a preprocessor directive to include text and binary resources directly into source code. This pattern is common in applications such as games that create custom fonts, load images into memory, etc. This allows the C preprocessor to replace external tools that convert resources to byte representations as C arrays.
The #embed preprocessor directive also includes optional parameters including suffix, prefix, and if_empty.
§§§ Enums with underlying type
C23 enums provide the ability to optionally specify the underlying type.
§§§ typeof
Gets the type of an expression, similar to decltype in C++. Also includes typeof_unqual which removes cv-qualifiers from the type.
§§§ Improved compatibility for tagged types
Tagged types that have the same tag name and content become compatible not only across translation units but also inside the same translation unit. Also, redeclaration of the same tagged types is now allowed.
|
|
§§ C23 Library Features
§§§ Floating-point formatting functions
Converts floating-point values to byte strings. Convert floats, doubles, and long doubles using strfromf, strfromd, and strfroml respectively.
§§§ memset_explicit
Copies the given value into each of the first count characters of the object pointed to by dest. Unlike memset, this function cannot be optimized away by the compiler; therefore, this function is guaranteed to perform the memory write.
§§§
unreachable macro
Provides a standard macro for (historically) compiler-specific macros for denoting an unreachable area of the code.
§§§
memccpy
Copies bytes from source to destination stopping after either the terminating byte is found (and also copied) or the given number of bytes is copied.
§§§
strdup and strndup
These functions duplicate a given string by allocating a buffer and copying. The returned string is always null-terminated. Be sure to free the memory returned by thhese functions after use.
§§§
gmtime_r and localtime_r
Works as gmtime and localtime does but uses a given storage buffer for the result. Returns a NULL pointer on error.
§§§
timespec_getres
Stores the resolution of time provided by the given base. Returns zero on failure.
§§ C11 Language Features
§§§ Generic selection
Using the _Generic keyword, select an expression based on the type of a given controlling expression. The format of _Generic is as follows:
_Generic( controlling-expression, T1: E1, ... )
where:
controlling-expresionis an expression that yields a type present in the type list (T1: E1, ...).T1is a type.E1is an expression.
Optionally, specifying default in a type list, will match any controlling expression type.
|
|
§§§ alignof
Queries the alignment requirement of a given type using the _Alignof keyword or alignof convenience macro defined in <stdalign.h>.
|
|
max_align_t is a type whos alignment is as large as that of every scalar type.
§§§ alignas
Sets the alignment of the given object using the _Alignas keyword, or alignof macro in <stdalign.h>.
max_align_t is a type whos alignment is as large as that of every scalar type.
§§§ static_assert
Compile-time assertion either using the _Static_assert keyword or the static_assert keyword macro defined in assert.h.
|
|
See: new keywords (C23).
§§§ noreturn
Specifies the function does not return. If the function returns, either by returning via return or reaching the end of the function body, its behaviour is undefined. noreturn is a keyword macro defined in <stdnoreturn.h>.
See: attributes.
§§§ Wide string literals
Create 16-bit or 32-bit wide string literals and character constants.
See: char32_t, char16_t, unicode string literals.
§§§ Anonymous structs and unions
Allows unnamed (i.e. anonymous) structs or unions. Every member of an anonymous union is considered to be a member of the enclosing struct or union, keeping the layout intact. This applies recursively if the enclosing struct or union is also anonymous.
§§ C11 Library Features
§§§ Bounds checking
Many standard library functions now have bounds-checking versions of existing functions. You can specify a callback function using set_constraint_handler_s as a constraint handler when a function fails its boundary check. The standard library includes two constraint handlers: abort_handler_s which writes to stderr and terminates the program; and ignore_handler_s ignores the violation and continue the program.
Standard library functions with bounds-checked equivalents will be appended with _s. For example, some bounds-checked versions include fopen_s, get_s, asctime_s, etc.
Example of a custom constraint handler with get_s:
If a user enters a string greater than or equal to BUFFER_SIZE the custom constraint handler will be called.
§§§ timespec_get
Populates a struct timespec object with the current time given a time base.
§§§ aligned_malloc
Allocates bytes of storage whose alignment is specified.
§§§ char32_t
An unsigned integer type for holding 32-bit wide characters.
See: wide string literals, char16_t, unicode string literals.
§§§ char16_t
An unsigned integer type for holding 16-bit wide characters.
See: wide string literals, char32_t, unicode string literals.
§§§ <stdatomic.h>
§§§§ Atomic types
The _Atomic type specifier/qualifier is used to denote that a variable is an atomic type. An atomic type is treated differently than non-atomic types because access to atomic types provide freedom from data races. For example, the following code was compiled on x86 clang 4.0.0:
Notice that the atomic type used a mov then an xchg instruction to assign the value 1 to a, while b uses a single mov. Other operations may include +=, ++, and so on… Ordinary read and write access to atomic types are sequentially-consistent.
See this StackOverflow post for more information.
A variety of typedefs exist which expand to _Atomic T. For example, atomic_int is typedef’d to _Atomic int. See this list for a more complete list.
Atomic types can also be tested for lock-freedom by using the atomic_is_lock_free function or the various ATOMIC_*_LOCK_FREE macro constants. Since atomic_flags are guaranteed to be lock-free, the following example will always return 1:
§§§§ Atomic flags
An atomic_flag is a lock-free (guaranteed), atomic boolean type representing a flag. An example of an atomic operation which uses a flag is test-and-set. Initialize atomic_flag objects using the ATOMIC_FLAG_INIT macro.
A simple spinlock implementation using atomic_flag as the “spin value”:
|
|
§§§§ Atomic variables
An atomic variable is a variable which is declared as an atomic type. Atomic variables are meant to be used with the atomic operations which operate on the values held by these variables (except for the flag operations, ie. atomic_flag_test_and_set). Unlike atomic_flag, these are not guaranteed to be lock-free. Initialize atomic variables using the ATOMIC_VAR_INIT macro or atomic_init if it has been default-constructed already.
The C11 Atomics library provides many additional atomic operations, memory fences, and allows specifying memory orderings for atomic operations.
|
|
§§§ <threads.h>
C11 provides an OS-agnostic thread library supporting thread creation, mutexes, and condition variables. Threading library is located in <threads.h>. As of September 2023, it is poorly supported in most major compilers.
§§§§ Threads
Creates a thread and executes print_n in the new thread.
§§§§ Mutexes
C11 provides mutexes that support:
- Timed locking - Given a
timespecobject, blocks the current thread until the mutex is locked or until it times out. - Recursive locking - Supports recursive locking (e.g. re-locking in recursive functions). Recursive timed locks can also be created, capturing both these operations.
Specify which type of mutex to be created by passing any of mtx_plain, mtx_timed, mtx_recursive, or any combination of these to mtx_init’s type parameter.
Mutexes must be cleaned up by calling mtx_destroy.
§§§§ Condition variables
C11 provides condition variables as part of its concurrency library. Condition variables will block when waiting, support timed-waiting, and can be signalled and broadcasted. Note that spurious wakeups may occur.
Condition variables must be cleaned up by calling cnd_destroy.
|
|
§§§ Quick exiting
Causes program termination to occur where clean termination is not possible or impractical; for example if cooperative cancellation between different threads is not possible or cancellation order is unachievable. This would have resulted in some threads trying to access static-duration objects while they are/have been destructed.
Quick exiting allows applications to register handlers to be called on exit while being able to access static duration objects (unlike atexit). Quick exiting does not execute static-duration object destructors in order to achieve this.
Therefore, quick exiting can be thought of as being “in between” choosing to normally terminate a program, and abnormally terminating using abort.
§§§ Exclusive mode file opening
File access mode flag x can optionally be appended to w or w+ specifiers. This flag forces the function to fail if the file exists, instead of overwriting it.
§ COPYING & ATTRIBUTIONS:
Author Anthony Calandra
License: The MIT License (MIT) Copyright (c) 2017 Anthony Calandra
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.