Document: n2593
Previous Revisions: None
Audience: WG14
Proposal Category: New Features
Target Audience: General Developers, Compiler/Tooling Developers
Latest Revision: https://thephd.github.io/vendor/future_cxx/papers/source/n2593.html
Abstract:
Getting the type of an expression in Standard C code.
Introduction & Motivationtypeof
is a extension featured in many implementations of the C standard to get the type of an expression. It works similarly to sizeof
, which runs the expression in an âunevaluated contextâ to understand the final type, and thusly produce a size. typeof
stops before producing a byte size and instead just yields a type name, usable in all the places a type currently is in the C grammar.
There are many uses for typeof
that have come up over the intervening decades since its first introduction in a few compilers, most notably GCC. It can, for example, help produce a type-safe generic printing function that even has room for user extension (see: https://slbkbs.org/tmp/fmt/fmt.h). It can also help write code that can use the expansion of a macro expression as the return type for a function, or used within a macro itself to correctly cast to the desired result of a specific computationâs type (for width and precision purposes). The use cases are vast and endless, and many people have been locking themselves into implementation-specific vendorship that have locked them out of other compilers (for example, Microsoftâs Visual C Compiler).
Every implementation in existence since C89 has an implementation of typeof
. Some compilers (GCC, Clang, EDG, tcc, and many, many more) expose this with the implementation extension typeof
. But, the Standard already requires typeof
to exist. Notably, with underlined emphasis added,
The
sizeof
operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. â N2573, §6.5.3.4 Thesizeof
and_Alignof
operators, Semantics
Any implementation that can process sizeof("foo")
is already doing sizeof(typeof("foo"))
internally. This feature is the most âexisting practiceâ-iest feature to be proposed to the C Standard, possibly in the entire history of the C standard.
Furthermore, putting a type or a VLA-type computation results in an idempotent type computation that simply yields that type in most implementations that support the feature.
WordingThe following wording is relative to N2573.
Adjust the Syntax grammar of §6.7.2 Type specifiers
type-specifier:
â âvoid
â â â¦
â â typedef-name
â â typeof-specifier
Add a new §6.7.2.5 The Typeof specifier
§6.7.2.5 â â The Typeof specifier Syntaxtypeof-specifier:
Constraints
â â_Typeof
unary-expression
â â_Typeof
( type-name )The typeof-specifier shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member.
SemanticsThe typeof-specifier applies the
_Typeof
operator to a unary-expression (6.5.3) or a type-specifier. If the_Typeof
operator is applied to a unary-expression, it yields the type-name representing the type of its operand11�0). Otherwise, it produces the type-name with any nested typeof-specifier evaluated 11�1). If the type of the operand is a variable length array type, the operand are evaluated; otherwise, the operand is not evaluated.Type qualifiers (6.7.3) of the type from the result of a
_Typeof
operation are preserved.11�0) When applied to a parameter declared to have array or function type, the
_Typeof
operator yields the adjusted (pointer) type (see 6.9.1).11�1) If the operand is a
_Typeof
operator, the operand will be evaluated before evaluating the current_Typeof
operation. This happens recursively until a typeof-specifier is no longer the operand.
Add the following examples to the new Typeof section
5 EXAMPLE 1 Type of an expression6 EXAMPLE 2 Equivalence of_Typeof(1) main () { return 0; } // equivalent to: // int main() { // ... // }
sizeof
andtypeof
.7 EXAMPLE 3 Nestedint main (int argc, char* argv[]) { // this program has no constraint violations _Static_assert(sizeof(_Typeof('p')) == sizeof(char)); _Static_assert(sizeof(_Typeof('p')) == sizeof('p')); _Static_assert(sizeof(_Typeof("meow")) == sizeof(char[5])); _Static_assert(sizeof(_Typeof("meow")) == sizeof("meow")); _Static_assert(sizeof(_Typeof(argc)) == sizeof(int)); _Static_assert(sizeof(_Typeof(argc)) == sizeof(argc)); _Static_assert(sizeof(_Typeof(argv)) == sizeof(char**)); _Static_assert(sizeof(_Typeof(argv)) == sizeof(argv)); return 0; }
_Typeof(...)
.8 EXAMPLE 4 Variable Length Arrays andint main (int argc, char*[]) { float val = 6.0f; // equivalent to a cast and return return (_Typeof(_Typeof(_Typeof(argc))))val; // return (int)val; }
_Typeof
.#include <stddef.h> size_t vla_size (int n) { typedef char vla_type[n + 3]; vla_type b; // variable length array return sizeof( _Typeof(b) ); // execution-time sizeof, translation-time _Typeof } int main () { return (int)vla_size(10); // vla_size returns 13 }
Add a new §7.� Typeof <stdtypeof.h>
The header
<stdtypeof.h>
defines two macros.The macro
typeof
expands to
_Typeof
.The macro
__typeof_is_defined
is suitable for use in
#if
preprocessing directives. It expands to the integer constant1
.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4