Logo
Articles Compilers Libraries Books MiniBooklets Assembly C++ Rust Linux CPU Others Videos
Advertisement

Article by Ayman Alheraki on February 11 2026 06:13 AM

C23 vs C++23 Are Variable Types Really Identical

C23 vs C++23: Are Variable Types Really Identical?

 

A Practical Comparison of the Type Systems in Modern C and Modern C++

One of the most common questions among C and C++ developers is:

Are variable types truly “the same” between the two languages? And can we consider them fully compatible at the type-system level?

The precise answer is:

There is significant overlap in fundamental types and their representations. However, there is no complete equivalence in language rules, type semantics, and behavior—especially when we examine implicit conversions, enums, pointers, atomics, and modern alignment features.

This article compares C23 and C++23, focusing strictly on the type system—where they match and where they differ.

1) What Changed in C23? (The bool Milestone)

Until C17, C supported Boolean types via a header:

With C23, this changed fundamentally:

  • bool is now a reserved keyword

  • true and false are keywords

  • <stdbool.h> is no longer required

So this is now valid:

This brings C syntactically closer to C++. But syntactic similarity does not imply full semantic equivalence.

2) Fundamental Types: Where True Compatibility Exists

The following fundamental types exist in both C23 and C++23:

  • char, signed char, unsigned char

  • short, int, long, long long

  • float, double, long double

On most platforms, their memory representations are identical. However, neither standard mandates exact bit sizes (except ordering relationships like sizeof(short) <= sizeof(int) <= sizeof(long)).

So practical compatibility depends on platform ABI, not just language specification.

3) bool: Similar Now — But Not Identical in Context

C23 and C++23 both define bool. The difference is not usually size—but how the language treats the type.

In C23:

  • bool is an integral type

  • Values normalize to 0 or 1

  • Implicit conversions are permissive

In C++23:

  • bool is also integral

  • Participates in overload resolution

  • Affects template specialization

  • Interacts with implicit conversion rules differently in some contexts

The type itself may look identical—but C++ surrounds it with a richer type system.

4) Fixed-Width Integer Types: The Engineering Foundation

For ABI-stable interfaces, both languages provide:

  • int32_t, uint64_t

  • intptr_t, uintptr_t

  • size_t, ptrdiff_t

In C23 via <stdint.h> and <stddef.h> In C++23 via <cstdint> and <cstddef> (typically under std::)

Here, compatibility is excellent. These are the recommended types for portable, low-level API design.

5) Pointers: Identical Representation, Different Rules

Pointer representation at the machine level is typically identical.

However, conversion rules differ significantly.

Conversion from void* to T*

In C23:

In C++23:

This is not cosmetic. C++ enforces stricter type safety and requires explicit conversions.

6) NULL vs nullptr: A Subtle but Important Difference

In C23:

In C++23:

nullptr has a dedicated type (std::nullptr_t) and prevents a classic C++ issue:

When functions are overloaded between int and pointer types, NULL may be treated as integer 0, leading to incorrect overload selection. nullptr resolves this cleanly.

C23 does not introduce nullptr.

7) enum: The Largest Type-System Divergence

In C23:

  • Implicitly convertible to int

  • Weakly typed

In C++23, the same is possible—but modern C++ adds:

This introduces:

  • Strong typing

  • No implicit conversion to integer

  • Explicit control over underlying type

For large-scale systems, enum class dramatically improves type safety.

8) struct: Same Data Model, Different Object Model

In C23, a struct is fundamentally a data aggregate.

In C++23, a struct may include:

  • Constructors and destructors

  • Member functions

  • Access control

  • Inheritance (if used)

However, there is a crucial compatibility zone:

If a C++ struct is:

  • Standard-layout

  • Trivially copyable

  • Without inheritance or virtual functions

Then it will typically match a C struct in memory layout.

This is the golden rule when designing C-compatible APIs in C++.

9) Atomics: Keyword vs Template Type

In C23:

In C++23:

Both rely on modern memory models. The difference lies in structure:

  • C: language-level keyword with procedural API

  • C++: template class with member functions and stronger abstraction

C++ provides a richer type-oriented interface around atomic operations.

10) _Generic vs Templates

C23 includes _Generic for compile-time type selection:

C++23 offers templates and concepts:

  • More powerful abstraction

  • Stronger compile-time enforcement

  • Richer type relationships

This reflects a deep philosophical divergence in type-system design.

Final Engineering Summary

We can analyze compatibility at three levels:

1) Representation & ABI Level

Fundamental types and fixed-width integers are largely compatible.

2) Syntax Level

C23 has moved closer to C++ (notably with bool, true, false, and alignment features).

3) Semantic & Type-System Level

C++ remains significantly richer and stricter due to:

  • Overloading

  • Templates and concepts

  • enum class

  • References

  • Object model rules

  • nullptr

  • Stronger type constraints

Practical Advice for C and C++ Developers

If you are building cross-language libraries or stable APIs:

  • Prefer int32_t, uint64_t over int and long

  • Avoid exposing C++-specific constructs across ABI boundaries

  • Use extern "C" in C++ for public interfaces

  • Keep shared structs standard-layout and trivial

  • Avoid mixing object models across language boundaries

This approach gives you the best of both worlds:

  • C++ power internally

  • C compatibility externally

Advertisements

Responsive Counter
General Counter
1166506
Daily Counter
902