It's been about one month since C3 0.5.3 (announcement) was released. Since then there has been quite a lot of non-breaking additions to the compiler and I'm happy to announce the release of 0.5.4 of the C3 programming language. (Grab the downloads here:

In terms of changes to the language, bitstructs have gotten some additional love, with == and != supported and bit operations on bitstructs are now folded at compile time for constant bitstructs.

Startup initialization / finalization for macOS got an overhaul and is now guaranteed to be ordered, despite the OS not supporting ordering. This finally made dynamic calls safe to use with init functions.

For the stdlib, memory functions are changing. The family of new functions are now zero initializing by default. The reason is subtle: with implicit zeroing of locals, it's natural to start assuming everything is zero by default, even with heap allocations. So having mem::new being non-initialized is the wrong default, the new convention is that new means zeroing allocation and alloc means non-zeroing allocation. So all the functions ending with "zero" and "clear" are deprecated in favor of just the default new.

Also, similarly how stream methods like file.printf(...) was abandoned for io::fprintf(file, ...), the many allocator methods are getting deprecated for removal in 0.6. To replace this, std::mem::allocator is getting malloc, free, new and other functions that take an allocator.

Some examples:

int* x = mem::new_zero(int);
int* y = mem::new(int);
// replaced by:
int* x = mem::new(int);
int* y = mem::alloc(int);

Foo* f =;
// replaced by:
Foo* f = allocator::new(my_allocator, Foo)

It might seem counterintuitive that allocator::new is preferable given that it's longer. However, it turns out it's much easier to work with than methods for a consistent set of functions to call.

In any case, most applications should prefer standard heap and temp allocations using the functions in std::mem.

Finally there's the addition of the experimental "GenericList", which is a tentative name. It can hold a heterogenous list of objects. The downside is that it requires more memory management as it's based around any*.

Changes / improvements

  • Hash variables may now take a designated initializer.
  • Added @safemacro to override the @ requirement for non-function-like macros.
  • More information available with debug log in non debug builds.
  • Removed install_win_reqs.bat which didn't work well.
  • Support ** to mean ./**
  • MacOS init/finalizer now respects priority.
  • Bitstructs supports != and ==.
  • Support Windows .def files using --windef.
  • Bitstructs now fold compile time constant bit ops.
  • Fix issue where in some cases a constant global with a string wasn't folded (e.g. in asm stmts)
  • Lateral implicit imports removed.
  • Default to '.' if no libdir is specified.
  • Improved error messages for --lib.
  • Added --linker to set the linker #1067.


  • Fixes to macro context evaluation with macro varargs.
  • Dynamic methods registered before init functions on MacOS.
  • Fixed clobber on x86 cpuid instruction.
  • Removed invalid syntax from grammar.y.
  • output project setting now respected.
  • Aliased declarations caused errors when used in initializers.
  • Aliased consts used as constant initializers caused errors.
  • Exported module names replace :: by _.
  • Const ternary would evaluate incorrectly for ?:
  • $$MODULE would report the incorrect module name in macros.
  • Fixed debug info for globals and for/switch scopes.
  • out now correctly detects subscript[] use.
  • Ambiguous recursive imports are now correctly detected.
  • Overzealous local escape check corrected #1127.
  • Fixes to the matrix functions #1130.

Stdlib changes

  • Deprecated Allocator helper functions.
  • Added mem::allocator functions corresponding to removed allocator functions.
  • Changed mem::new / mem::temp_new to accept an optional initializer, and will clear by default.
  • Mem _clear and _zero variants deprecated. "new_*" functions will clear by default.
  • Mem "alloc_" functions replace old "new_" behaviour.
  • Fixed temp memory issue with formatter.
  • Added temp_push and temp_pop for pushing / popping the temp allocator manually (or from C).
  • Added byte_size to List
  • Added GenericList.

0.5 has feature stability guarantees, so any code written for 0.5.0 will with on all of 0.5.x.

If you want to read more about C3, check out the documentation: or download it and try it out: