ORCA/C 2.3.0 B1 Copyright 1997, Byte Works Inc. Updated by Stephen Heumann and Kelvin Sherlock, 2017-2026 These release notes document the changes between ORCA/C 2.2.1 and ORCA/C 2.3.0 B1. For changes between ORCA/C 2.0 and ORCA/C 2.2.1, refer to the ORCA/C 2.2.1 release notes. -- Change List -------------------------------------------------------------- 2.3.0 B1 1. Bugs squashed. See bug notes, below. 2. New C23 language and library features added. See "New Language Features" and "Library Updates," below. -- Compiler changes introduced in C 2.3.0 ----------------------------------- New Language Features --------------------- ORCA/C 2.3.0 has begun adding support for new language features from the recent C23 standard. The default language mode is now "c23compat", which includes all available C23 features but also includes some extensions and continues to support some features from earlier standards. A "c23" language mode that strictly follows the C23 standard is also available. C23 features that are unlikely to cause compatibility problems are also available in pre-C23 compatibility modes such as "c17compat" mode. Features only available in C23 modes are indicated below. The following C23 language features are currently implemented: 1. (C23 modes only) ORCA/C now recognizes the new keywords added in C23. These are: alignas alignof bool constexpr false nullptr static_assert thread_local true typeof typeof_unqual _BitInt _Decimal128 _Decimal32 _Decimal64 Of these, alignas, alignof, bool, static_assert, and thread_local are equivalent to the existing _Alignas, _Alignof, _Bool, _Static_assert, and _Thread_local keywords, respectively. true, false, typeof, typeof_unqual, nullptr, and _BitInt are described below. The other new C23 keywords are recognized as keywords, but the corresponding language features are not yet supported, so any attempt to use them will produce an error message. 2. (C23 modes only) Trigraphs are no longer supported, and character sequences that would have been interpreted as trigraphs can now be used normally, e.g. within string literals. 3. (C23 modes only) u8-prefixed string literals have an "array of unsigned char" type, rather than "array of char". 4. static_assert or _Static_assert can now be used in a one-argument form: static_assert ( constant-expression ) ; 5. When a macro taking a variable number of arguments is invoked with no arguments corresponding to the variable portion of the argument list, the final comma may be omitted. For example, a macro defined like #define m(x, ...) /*...*/ may be invoked as m(1) 6. Universal character names (UCNs) within string literals or character constants can now designate any valid Unicode code point, including ASCII characters or control characters. 7. (C23 modes only) The validity of UCNs within identifiers is now defined based on the XID_Start and XID_Continue Unicode properties. 8. Attribute specifiers of the form [[ /*...*/ ]] may appear in certain places in declarations and statements, declaring attributes that appertain to various syntactic elements. ORCA/C currently ignores all attributes. The __has_c_attribute preprocessor operator is also available for use within preprocessor expressions. It is followed by parentheses enclosing an attribute name. It expands to 0 if the attribute is not supported, or a non-zero value if it is supported. Since ORCA/C does not currently support any attributes, it always expands to 0 in ORCA/C. 9. Labels are no longer restricted to appearing only before statements. They can now appear before declarations (within a function body) or immediately before the closing } of a compound statement. 10. Character constants can now have the u8 prefix, indicating UTF-8 encoding. Such character constants have the type unsigned char. Unless designated by an octal or hexadecimal escape sequence, the character specified by a u8-prefixed character constant must be one that can be represented by a single UTF-8 code unit, i.e. a character within the 7-bit ASCII character set. 11. The #elifdef and #elifndef preprocessor directives are now supported: #elifdef identifier #elifndef identifier The first is equivalent to #elif defined identifier and the second is equivalent to #elif !defined identifier 12. (C23 modes only) The new keywords true and false denote predefined constants with type bool and values 1 and 0, respectively. If true is used in a preprocessor expression, it is replaced with 1, unlike other identifiers or keywords (including false) that are replaced with 0. This means that true and false can effectively be used as boolean constants within preprocessor expressions, as well as in regular C code. 13. (C23 modes only) Type specifiers using typeof or typeof_unqual are now supported. They can have the following forms: typeof ( expression ) typeof ( type-name ) typeof_unqual ( expression ) typeof_unqual ( type-name ) These can appear wherever type specifiers are used, e.g. in declarations. The forms with typeof specify either the type of the expression or the type designated by the type name. The forms with typeof_unqual are similar, except that they will remove any qualifiers (e.g. const or volatile) from the type. 14. (C23 modes only) Type inference is now supported in variable definitions. This applies to declarations that meet all of the following requirements: - They contain the storage class specifier auto - They do not contain any type specifiers - They contain exactly one declarator, declaring one variable - The declarator is not a pointer, array, or function declarator - There is an initializer for the variable - The initializer is an expression, not enclosed in braces - There was no previous declaration of the variable in the same scope In declarations meeting these requirements, the type of the variable is inferred to be the type of the initializer expression, with array or function types converted to pointer types, any qualifiers from the type of the expression removed, and any type qualifiers that appear in the declaration added. In such declarations, auto effectively acts like a type specifier indicating that the type should be inferred, rather than as a storage class specifier. Therefore, it may be used even in places where an auto storage class specifier would otherwise not be permitted, such as in declarations at file scope or declarations that contain other storage class specifiers. For example, the declaration static auto x = 123L; declares the variable x with type long (because that is the type of 123L) and static storage class. Note that this can change the behavior of code written using the "implicit int" feature of C89/C90, where a declaration with no type specifiers would behave as if the type specifier int was included. In the "c23compat" language mode, declarations that use auto with no type specifiers but do not meet all the other requirements above will still be processed using the "implicit int" rule. In "c23" mode or when #pragma lint bit 6 is set, they will produce a lint message. 15. Variable length array types are now supported. These are array types where the array length expression enclosed in brackets is not an integer constant expression but instead an expression that needs to be evaluated at execution time. Such array types may occur only in function parameters or within a function body. The array length expression is normally evaluated when the declaration or type name that contains it appears in the code (or at the beginning of the function, in the case of expressions within function parameter declarations). It must evaluate to a positive value, and this then determines the size of the array type for as long as it remains in scope. Functions can be defined as taking variable length array parameters (including multi-dimensional arrays) with the array sizes defined by other function parameters. Such functions can be used to operate on arrays of various different sizes depending on the parameters passed to them at run time. This can be useful for functions performing mathematical operations, e.g. matrix multiplies. Note that ORCA/C does not allow local variables to have variable length array types. This is an optional feature in the C23 standard, which ORCA/C does not implement. As an alternative, it is possible to declare a pointer to a variable length array type and then allocate space for the array with malloc() based on the desired size as determined at run time. 16. The #embed preprocessor directive is now supported. It can have one of these forms: #embed "filename" [parameters] #embed [parameters] The #embed directive embeds the bytes from the specified file into the C source file as a comma separated list of integer constants. For example, if there is a file "testfile" that contains only the word "hello", then the directive #embed "testfile" will expand to the token sequence 104,101,108,108,111 because those numbers correspond to the ASCII values of the characters 'h', 'e', 'l', 'l', and 'o'. The two forms of the #embed directive search for a file in the same way as the #include directive would, except that the file is not required to have the SRC file type. Thus, the form with "filename" looks in the current directory first, while the form with looks in the ORCACDefs directory first. As with #include, the search path can be modified with #pragma path. Either form of the #embed directive may also optionally include one or more parameter clauses of the following forms after the file name: limit(expression) if_empty(tokens) prefix(tokens) suffix(tokens) The limit clause takes an integer constant expression which limits the number of bytes to embed from the file. The if_empty clause contains an alternate token sequence that will be used if no bytes can be embedded from the file, either because it was empty or because limit(0) was specified. The prefix and suffix clauses specify extra tokens that will be included before or after those embedded from the file, provided that at least one byte is embedded from the file. In the token sequences in the if_empty, prefix, and suffix clauses, any parentheses, brackets, or braces must be balanced and properly nested. The #embed directive is primarily useful for embedding the contents of small files into the C program. For example, it might be used to embed a small image into the program by using the embedded token sequence from an image file to initialize an array. Note that embedding large files may cause ORCA/C to run out of memory or encounter other limitations; other approaches such as using resources are generally better in those cases. The __has_embed preprocessor operator is also available for use within preprocessor expressions. It is followed by parentheses enclosing a filename and optional parameters, like the arguments for the #embed directive. It expands to a value that matches one of the following predefined macros, indicating how an #embed directive with the specified filename and parameters would behave: a) __STDC_EMBED_NOT_FOUND__ (a value of 0), indicating that the file could not be found or an unsupported parameter was used, so a corresponding #embed directive would produce an error b) __STDC_EMBED_FOUND__ (a value of 1), indicating that the file was found and the corresponding #embed directive would embed one or more bytes from it c) __STDC_EMBED_EMPTY__ (a value of 2), indicating that the file was found, but the file was empty or limit(0) was specified, so the corresponding #embed directive would not embed any bytes from it 17. The __has_include preprocessor operator is available for use within preprocessor expressions. It is followed by parentheses enclosing a filename in quotes or angle brackets, like the argument for the #include directive. It searches for a file in the same way the #include directive would and expands to 1 if a file of the specified name is available to include, or 0 if not. 18. (C23 modes only) C23 removes support for function declarators without prototypes. K&R-style function definitions with a parameter name list are no longer permitted. Function declarators like f() are still permitted, but a declarator like this is now considered equivalent to f(void) -- that is, it provides a prototype for a function with no parameters. ORCA/C now supports these rules in C23-based language modes. However, to provide better compatibility with old code, a new #pragma ignore option is provided that can partially revert to the older rules. If a C23-based language mode is used but #pragma ignore bit 6 is set, then K&R-style function definitions with parameter name lists will be permitted, and declarations like int f(); are largely treated as if they did not provide a prototype. A call to a function declared like this will be allowed to pass any number of arguments, and a subsequent definition of the function may include parameters. However, a function definition (not declaration) with an empty parameter list is still treated as providing a prototype for the function with no parameters. Also, _Generic expressions will use the C23 type compatibility rules for determining which association to use, regardless of the setting of #pragma ignore bit 6. #pragma ignore bit 6 is set by default in the "c23compat" language mode, but it is clear by default in "c23" mode. It has no effect in pre-C23 language modes, where the rules from the earlier standards are always followed. 19. Bit-precise integer types are now supported. These are designated by type specifiers of the form _BitInt(N) or unsigned _BitInt(N), where N is an integer constant expression. The value of N gives the width of the type (the number of value bits). _BitInt(N) designates a signed N-bit integer type using two's-complement representation; N can range from 2 to 64. unsigned _BitInt(N) designates an unsigned N-bit integer type; N can range from 1 to 64. These types are distinct from the traditional C integer types (e.g. int), even though they may sometimes have the same width. In ORCA/C, bit-precise integer types are stored in memory using 16, 32, or 64 bits, whichever is needed to fit them. If N is not exactly one of those values, then the N-bit value is sign-extended (for signed _BitInt types) or zero-extended (for unsigned _BitInt types) to the width used to store it. Note that the unary and binary conversion rules do not apply to _BitInt types in the same way that they do to other integer types. In particular, _BitInt types narrower than int are not automatically promoted to int or unsigned int. For example, the result of adding two _BitInt(4) values has type _BitInt(4) and is restricted to the range of _BitInt(4). (If the resulting value would overflow that range, the behavior is undefined.) A suffix of wb or WB can be used on an integer constant to give it a _BitInt type that is just wide enough to hold the specified value. If a wb or WB suffix is used together with u or U, then the constant has an unsigned _BitInt type just wide enough to hold the value. For example, 6wb has the type _BitInt(4), while 6WBU has the type unsigned _BitInt(3). 20. The empty initializer {} is now supported. This functions similarly to the initializer {0}, but when initializing structures or unions it also guarantees that any padding is initialized to zero bits. 21. (C23 modes only) The new keyword nullptr denotes a predefined null pointer constant. It can be assigned or converted to any pointer type, yielding a null pointer value of that type. The type of nullptr is nullptr_t, which is given by a typedef in . It is possible to create variables of type nullptr_t, but this is rarely useful; the only value they can hold is nullptr. 22. Enumeration types have been enhanced in several ways. First, it is now possible to explicitly specify the underlying integer type that the enumeration type will be be compatible with. This is done by including a : and then a type name denoting an integer type in between the enum tag (if present) and the { beginning the enumerator list (if present). When this is done, the enumeration and the enumeration constants within it will have a type compatible with that integer type, and the constants can have any values within the range of that type. For example, this enumeration specifier declares an enumeration type compatible with long and three enumeration constants of that type: enum X : long {A = 1000000, B, C} Second, even if the underlying type is not specified explicitly, enumeration constant values are no longer limited to the range of int. In this case, the underlying integer type will be automatically selected to be able to hold all the values in the enumeration. In ORCA/C, it will be the first type from the following list that can hold all the values: int, unsigned int, long, unsigned long, long long, unsigned long long. Thus, in ORCA/C, this enumeration specifier functions similarly to the above one, also declaring an enumeration type compatible with long and three enumeration constants of that type: enum X {A = 1000000, B, C} Furthermore, it it now permitted to redeclare an enumeration type and its enumeration constants within the same scope. That is, two or more full enumeration specifiers for the same type may appear in the same scope. They must agree in the names and values of the enumeration constants, and if any of them include an explicitly specified underlying type, they must all do so. 23. Functions taking a variable number of arguments are no longer required to have any fixed parameters. For example, a function can be defined like: void f(...) { /*...*/ } The arguments can be accessed within the function using va_start, va_arg, and va_end, as in other functions taking a variable number of arguments. (Note that the name of the last fixed parameter no longer needs to be passed to va_start; see below under "Library Updates".) 24. (C23 modes only) Two complete structure or union types declared with the same tag in different scopes are now considered compatible, provided that they have matching fields (declared in the same order, with corresponding fields having the same names and compatible types). 25. Two or more full structure or union specifiers for the same type (including the field list) may now appear within the same scope. The name and type of each field must be exactly the same in each place it is defined. Library Updates --------------- ORCA/C now includes some new library functions and features specified by the C23 standard: 1. The and headers contain new *_WIDTH macros, giving the width (number of value bits) of various integer types. 2. The function-like macro unreachable() has been added: #include void unreachable(void); An invocation of this macro indicates that the control-flow path leading to it is unreachable. This could be used for optimization or to help diagnose errors, but ORCA/C currently ignores it. 3. The va_start() macro is now defined like: #include void va_start(va_list ap, ...); Only the va_list argument is required. The previously-required second argument giving the name of the last fixed parameter is no longer required and is ignored if present. 4. The call_once function has been added: #include typedef short once_flag; #define ONCE_FLAG_INIT 0 void call_once(once_flag *flag, void (*func)(void)); The call_once function uses a condition variable of type once_flag to ensure that a function is called exactly once. If the condition variable pointed to by flag has been initialized with the value ONCE_FLAG_INIT and not subsequently modified, call_once will call func() and also set *flag to a different value that indicates func() has been called; otherwise, it will not call func(). Thus, if call_once is invoked one or more times with the same condition variable, it will ensure that func() is called exactly once. Any call to call_once will only return once func() has completed, whether from that call to call_once or a previous one. 5. The memset_explicit function has been added: #include void *memset_explicit(void *ptr, int val, size_t len); This does the same thing as memset, but is intended for use when clearing sensitive data. Some compilers may optimize out certain calls to memset; using memset_explicit instead indicates that they should not do that. ORCA/C does not perform such optimizations, so it just treats the two functions as equivalent. 6. The memccpy function has been added: #include void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n); This function copies bytes from src to dest until the byte value c (converted to unsigned char) is copied or until n bytes have been copied, whichever happens first. If the byte c was copied, it returns a pointer to immediately after that byte in dest; otherwise, it returns a null pointer. If the source and destination memory areas overlap, the results are unpredictable. 7. The free_sized and free_aligned_size functions have been added: #include void free_sized(void *ptr, size_t size); void free_aligned_sized(void *ptr, size_t alignment, size_t size); The free_sized function is like free, except that it includes a parameter giving the size requested when allocating the memory; it may be used to free memory allocated with malloc, calloc, or realloc. The free_aligned_sized function is similar, but also includes the originally requested alignment; it may be used to free memory allocated with aligned_alloc. The size and (if applicable) alignment must match those requested when allocating the memory; if they do not, the behavior is undefined. In some implementations these functions may be faster than free, but in ORCA/C they are not. 8. (C23 modes only) bsearch, memchr, strchr, strrchr, strpbrk, strrpbrk, and strstr are now generic functions, meaning that their return type depends on the type of one of their parameters (the second parameter for bsearch and the first parameter for all the others). If that parameter is a pointer to a const-qualified type, then the return type will be modified so that its pointed-to type is also const-qualified. For example, an expression like memchr((const char *)buf, 'x', 123) will have the type const void *, rather than void *. This avoids the previous situation where these functions would return a pointer into the same array passed to them but would discard any const qualifier that might apply to the data in that array. This behavior is implemented via macros; if the use of a macro is suppressed to access the actual functions, they will have the same return types as previously and will not be generic functions. 9. The fprintf() and fscanf() families of functions now support some new and updated conversion specifiers and length modifiers: In programs compiled using C23 language modes, the 'b' conversion specifiers have a new meaning in the fprintf and fscanf families of functions. These conversion specifiers are now used for output and input of integers in binary (base two) format. The corresponding parameter should be an unsigned integer (for fprintf) or a pointer to an unsigned integer (for fscanf). The integer type to use defaults to unsigned int but may be modified by length modifiers in the same way as for 'x' conversions. If the precision is specified in fprintf 'b' conversions, it works the same way as for 'x' conversions. If the # flag is used in fprintf 'b' conversions, the number is preceded by a leading 0b unless the value is 0; the + and space flags are not used. fscanf 'b' conversions accept an optional leading sign, then an optional leading 0b or 0B, then a sequence of binary digits (0 or 1). Note that this differs from the historical ORCA/C usage of 'b' conversion specifiers for output and input of strings with a leading length byte (p-strings). The older behavior is still available for programs compiled using C17 or earlier language modes, but to support C23 modes code should be changed to use 'P' conversion specifiers instead. These work exactly like the historical ORCA/C 'b' conversion specifiers, even in C23 modes. To enhance compatibility with existing code using the historical ORCA/C 'b' conversions, a new #pragma extensions flag (bit 2) has also been introduced. This will analyze the format strings and arguments passed to the fprintf and fscanf families of functions and identify places where 'b' conversions are used for p-strings. When it finds such usages, it will automatically change the 'b' to a 'P' in the format string. This allows most code relying on the historical 'b' conversions to continue working without changes; however, it only works when the function is called directly (not via a function pointer) and the format string is a string constant. #pragma extensions bit 2 is enabled by default in c23compat mode. (If #pragma lint bit 4 is enabled in C23 language modes, it will still produce lint messages about any 'b' conversions used for p-strings.) The 'B' conversion specifier is also now supported in the fprintf family of functions. This is identical to the C23 'b' conversion specifier, except that the prefix (if called for using the # flag) will be 0B rather than 0b. The 'B' conversion specifier is an optional feature of C23, so it may not be available in some other implementations, but in ORCA/C it is always available, even in pre-C23 language modes. In programs compiled using C23 language modes, the 'i' conversion specifier in the fscanf family of functions has also been updated to accept binary numbers identified by a 0b or 0B prefix, in addition to the decimal, hexadecimal, and octal formats it already accepted. In addition to the new and updated conversion specifiers, several new length modifiers are also now supported in the fprintf and fscanf families of functions. These length modifiers consist of 'w' or 'wf' followed by a number, and they correspond to integer types defined in , as follows: w8 corresponds to int8_t, int_least8_t, uint8_t, or uint_least8_t. w16 corresponds to int16_t, int_least16_t, uint16_t, or uint_least16_t. w32 corresponds to int32_t, int_least32_t, uint32_t, or uint_least32_t. w64 corresponds to int64_t, int_least64_t, uint64_t, or uint_least64_t. wf8 corresponds to int_fast8_t or uint_fast8_t. wf16 corresponds to int_fast16_t or uint_fast16_t. wf32 corresponds to int_fast32_t or uint_fast32_t. wf64 corresponds to int_fast64_t or uint_fast64_t. These may be used with d, i, o, u, x, X, B, or (in C23 modes) b conversions in the fprintf family of functions, in which case the corresponding argument must have one of the indicated types. They may also be used with n conversions in the fprintf family of functions, or with d, i, o, u, x, X, n, or (in C23 modes) b conversions in the fscanf family of functions; in these cases, the corresponding argument must be a pointer to one of the indicated types. 10. In programs compiled using C23 language modes, the strto(u)l, strto(u)ll, strtoimax, and strtoumax functions have been updated to better support numbers in binary (base two) format. If the base parameter is 0, they can now accept binary numbers identified by a 0b or 0B prefix, in addition to the decimal, hexadecimal, and octal formats that were already accepted. An optional 0b or 0B prefix is also now permitted if the base parameter is 2. 11. The timespec_getres function has been added: #include int timespec_getres(struct timespec *ts, int base); This function sets the structure *ts to represent the resolution of the time base indicated by the base parameter (which should be a macro value defined in ). That is, it indicates how frequently the time value for that time base will be updated. If the specified time base is supported, it returns the value of base; otherwise, it returns 0. The only time base supported by ORCA/C is TIME_UTC, which has a resolution of one second. The time in that time base can be obtained using timespec_get(); see its documentation for more information. 12. The localtime_r and gmtime_r functions have been added: #include struct tm *localtime_r(const time_t *t, struct tm *tmptr); struct tm *gmtime_r(const time_t *t, struct tm *tmptr); These are the same as localtime and gmtime, except that they write the broken-down time to *tmptr, rather than to an internal static buffer. They return tmptr. 13. The timegm function has been added: #include time_t timegm(struct tm *tmptr); This is similar to mktime, except that the input time structure is taken as representing UTC time rather than local time. By default, ORCA/C assumes local time is the same as UTC time, so timegm will return the same value as mktime. If __useTimeTool has been set to a non-zero value, ORCA/C will instead use the third-party Time Tool Set to get the offset between local time and UTC time and adjust the returned value accordingly. See the description of __useTimeTool for more information about the Time Tool Set. 14. The memalignment function has been added: #include size_t memalignment(const void *p); This returns the maximum alignment satisfied by the address p. That is, it returns the greatest power of two which the ordinal value of p is a multiple of. If p is a null pointer, it returns 0. 15. The strdup and strndup functions have been added: #include char *strdup(const char *s); char *strndup(const char *s, size_t n); The strdup function makes a copy of the string s in memory allocated by malloc. The strndup function is similar, but copies a maximum of n characters from s. (The resulting string is null-terminated, even if s does not include a null terminator within the first n characters.) These functions return a pointer to the copied string, or NULL if memory cannot be allocated for the copy. Like any allocation from malloc, the memory containing the copied string can be deallocated by calling free. 16. The strfromd, strfromf, and strfroml functions have been added: #include int strfromd(char *restrict s, size_t n, const char *restrict format, double val); int strfromf(char *restrict s, size_t n, const char *restrict format, float val); int strfroml(char *restrict s, size_t n, const char *restrict format, long double val); These functions produce a string representation of a floating-point number. They behave equivalently to snprintf(s, n, format, val), except that the format string must consist only of a single conversion specification with the following elements: - the initial % - optionally, a precision of the form .number (not containing a *) - one of the following conversion specifiers: a, A, e, E, f, F, g, or G The conversion specification is taken as applying to the type of val, even though it does not include a length modifier. If the format string is not of the form specified above, the behavior is undefined. 17. Several new functions have been added. Like other functions, most of these have three versions operating on the three floating-point types (but for most of these functions the three versions will behave identically). Also note that under ORCA/C these functions report errors via the floating-point environment (accessible using functions), not by setting errno. #include long llogb(double x); long llogbf(float x); long llogbl(long double x); These functions extract the binary exponent of x as a long integer, treating denormalized numbers as if they were normalized. If x is 0, infinite, or NaN, they return the macro values FP_LLOGB0, LONG_MAX, or FP_LLOGBNAN, respectively. #include float fadd(double x, double y); float faddl(long double x, long double y); double daddl(long double x, long double y); float fsub(double x, double y); float fsubl(long double x, long double y); double dsubl(long double x, long double y); float fmul(double x, double y); float fmull(long double x, long double y); double dmull(long double x, long double y); float fdiv(double x, double y); float fdivl(long double x, long double y); double ddivl(long double x, long double y); float fsqrt(double x); float fsqrtl(long double x); double dsqrtl(long double x); These functions perform the indicated operation (addition, subtraction, multiplication, division, or square root) on the operand(s) and round the result once to the range and precision of the result type. This has a similar effect to performing the arithmetic operations normally and then casting to the result type, but using these functions instead avoids double rounding. #include double pown(double x, long long n); float pownf(float x, long long n); long double pownl(long double x, long long n); These functions compute x^n. They are similar to pow(), put these functions use the type long long for the exponent (and as such it is restricted to integer values). #include double compoundn(double x, long long n); float compoundnf(float x, long long n); long double compoundnl(long double x, long long n); These functions compute (1+x)^n. If x < -1, a domain error occurs: the functions will return a NaN and raise the "invalid" floating-point exception. #include double logp1(double x); float logp1f(float x); long double logp1l(long double x); These functions return the natural logarithm of 1+x. (They are equivalent to the existing log1p functions.) #include double log2p1(double x); float log2p1f(float x); long double log2p1l(long double x); These functions return the base-2 logarithm of 1+x. #include double log10p1(double x); float log10p1f(float x); long double log10p1l(long double x); These functions return the base-10 logarithm of 1+x. #include double exp10(double x); float exp10f(float x); long double exp10l(long double x); These functions return 10^x. #include double exp2m1(double x); float exp2m1f(float x); long double exp2m1l(long double x); These functions return 2^x - 1. #include double exp10m1(double x); float exp10m1f(float x); long double exp10m1l(long double x); These functions return 10^x - 1. #include double rsqrt(double x); float rsqrtf(float x); long double rsqrtl(long double x); These functions return the reciprocal of the square root of x. #include double acospi(double x); float acospif(float x); long double acospil(long double x); double asinpi(double x); float asinpif(float x); long double asinpil(long double x); double atanpi(double x); float atanpif(float x); long double atanpil(long double x); double atan2pi(double y, double x); float atan2pif(float y, float x); long double atan2pil(long double y, long double x); These functions compute acos(x)/pi, asin(x)/pi, atan(x)/pi, or atan2(y,x)/pi. They can be seen as expressing an angle in units of half-revolutions. #include double cospi(double x); float cospif(float x); long double cospil(long double x); double sinpi(double x); float sinpif(float x); long double sinpil(long double x); double tanpi(double x); float tanpif(float x); long double tanpil(long double x); These functions compute the cosine, sine, or tangent of x*pi. Thus, the argument can be seen as expressing an angle in units of half-revolutions. For large values of x, these functions provide greater accuracy than corresponding calls to cos, sin, or tan (with x multiplied by an approximation of pi). #include double roundeven(double x); float roundevenf(float x); long double roundevenl(long double x); These functions round x to the nearest integer, rounding halfway cases to an even integer, regardless of the current rounding direction. #include double nextup(double x); float nextupf(float x); long double nextupl(long double x); double nextdown(double x); float nextdownf(float x); long double nextdownl(long double x); These functions return the next value greater than or less than x that is representable in the return type of the function. If that value is zero, it has the same sign as x. nextup(INFINITY) or nextdown(-INFINITY) returns the argument value. #include int canonicalize(double *cx, const double *x); int canonicalizef(float *cx, const float *x); int canonicalizel(long double *cx, const long double *x); These functions read the floating-point value from *x and attempt to write a canonical version of it to *cx. This means that *cx will have the same value as *x but may sometimes have a different bit pattern that follows the implementation's usual or preferred way of representing that value. If *x is a signaling NaN, *cx is set to a quiet NaN with the same NaN code. These functions return 0 if they succeed, or nonzero if the value cannot be canonicalized; in ORCA/C, they always succeed. 18. Several new function-like macros for classification of floating-point numbers have been added: #include int issubnormal(real-floating x); int iszero(real-floating x); int iscanonical(real-floating x); These macros accept an argument of any real floating type, i.e. float, double, or long double. They behave as if the argument is converted strictly to its semantic type before classifying it, removing any extra range and precision. issubnormal() returns a non-zero value if its argument is subnormal. iszero() returns a non-zero value if its argument is zero. iscanonical() returns a non-zero value if its argument has a canonical representation, i.e. if its bit pattern matches the usual or preferred way to represent its value. 19. The iseqsig() macro has been added: #include int iseqsig(real-floating x, real-floating y); This macro returns the value of (x)==(y). If x or y is a NaN, it signals the "invalid" floating-point exception. (In the current version of ORCA/C, the == operator usually also signals "invalid" for NaN operands, but that behavior is not guaranteed and may be changed in the future.) 20. Several new functions operating on the bit-level representation of numbers have been added. These are defined in the new header , and for each function family there is one function operating on each of the standard unsigned integer types (excluding bool), as well as a type-generic macro that can operate on any of those types or on unsigned _BitInt(N) types where N matches the width of any of those types. The type-generic macros have no type suffix, while each of the functions has a suffix corresponding to the type it operates on. #include unsigned int stdc_leading_zeros(unsigned-integer value); unsigned int stdc_leading_zeros_uc(unsigned char value); unsigned int stdc_leading_zeros_us(unsigned short value); unsigned int stdc_leading_zeros_ui(unsigned int value); unsigned int stdc_leading_zeros_ul(unsigned long value); unsigned int stdc_leading_zeros_ull(unsigned long long value); These functions return the number of leading zero bits in value. #include unsigned int stdc_leading_ones(unsigned-integer value); unsigned int stdc_leading_ones_uc(unsigned char value); unsigned int stdc_leading_ones_us(unsigned short value); unsigned int stdc_leading_ones_ui(unsigned int value); unsigned int stdc_leading_ones_ul(unsigned long value); unsigned int stdc_leading_ones_ull(unsigned long long value); These functions return the number of leading one bits in value. #include unsigned int stdc_trailing_zeros(unsigned-integer value); unsigned int stdc_trailing_zeros_uc(unsigned char value); unsigned int stdc_trailing_zeros_us(unsigned short value); unsigned int stdc_trailing_zeros_ui(unsigned int value); unsigned int stdc_trailing_zeros_ul(unsigned long value); unsigned int stdc_trailing_zeros_ull(unsigned long long value); These functions return the number of trailing zero bits in value. #include unsigned int stdc_trailing_ones(unsigned-integer value); unsigned int stdc_trailing_ones_uc(unsigned char value); unsigned int stdc_trailing_ones_us(unsigned short value); unsigned int stdc_trailing_ones_ui(unsigned int value); unsigned int stdc_trailing_ones_ul(unsigned long value); unsigned int stdc_trailing_ones_ull(unsigned long long value); These functions return the number of trailing one bits in value. #include unsigned int stdc_count_zeros(unsigned-integer value); unsigned int stdc_count_zeros_uc(unsigned char value); unsigned int stdc_count_zeros_us(unsigned short value); unsigned int stdc_count_zeros_ui(unsigned int value); unsigned int stdc_count_zeros_ul(unsigned long value); unsigned int stdc_count_zeros_ull(unsigned long long value); These functions return the total number of zero bits in value. #include unsigned int stdc_count_ones(unsigned-integer value); unsigned int stdc_count_ones_uc(unsigned char value); unsigned int stdc_count_ones_us(unsigned short value); unsigned int stdc_count_ones_ui(unsigned int value); unsigned int stdc_count_ones_ul(unsigned long value); unsigned int stdc_count_ones_ull(unsigned long long value); These functions return the total number of one bits in value. #include unsigned int stdc_first_leading_zero(unsigned-integer value); unsigned int stdc_first_leading_zero_uc(unsigned char value); unsigned int stdc_first_leading_zero_us(unsigned short value); unsigned int stdc_first_leading_zero_ui(unsigned int value); unsigned int stdc_first_leading_zero_ul(unsigned long value); unsigned int stdc_first_leading_zero_ull(unsigned long long value); These functions return the position of the first zero bit in value (counting from the most significant bit), where the most significant bit is numbered as position 1 and successive lower-order bits have successively higher numbers. If there are no zero bits in value, 0 is returned. #include unsigned int stdc_first_leading_one(unsigned-integer value); unsigned int stdc_first_leading_one_uc(unsigned char value); unsigned int stdc_first_leading_one_us(unsigned short value); unsigned int stdc_first_leading_one_ui(unsigned int value); unsigned int stdc_first_leading_one_ul(unsigned long value); unsigned int stdc_first_leading_one_ull(unsigned long long value); These functions return the position of the first one bit in value (counting from the most significant bit), where the most significant bit is numbered as position 1 and successive lower-order bits have successively higher numbers. If there are no one bits in value, 0 is returned. #include unsigned int stdc_first_trailing_zero(unsigned-integer value); unsigned int stdc_first_trailing_zero_uc(unsigned char value); unsigned int stdc_first_trailing_zero_us(unsigned short value); unsigned int stdc_first_trailing_zero_ui(unsigned int value); unsigned int stdc_first_trailing_zero_ul(unsigned long value); unsigned int stdc_first_trailing_zero_ull(unsigned long long value); These functions return the position of the first zero bit in value (counting from the least significant bit), where the least significant bit is numbered as position 1 and successive higher-order bits have successively higher numbers. If there are no zero bits in value, 0 is returned. #include unsigned int stdc_first_trailing_one(unsigned-integer value); unsigned int stdc_first_trailing_one_uc(unsigned char value); unsigned int stdc_first_trailing_one_us(unsigned short value); unsigned int stdc_first_trailing_one_ui(unsigned int value); unsigned int stdc_first_trailing_one_ul(unsigned long value); unsigned int stdc_first_trailing_one_ull(unsigned long long value); These functions return the position of the first one bit in value (counting from the least significant bit), where the least significant bit is numbered as position 1 and successive higher-order bits have successively higher numbers. If there are no one bits in value, 0 is returned. #include bool stdc_has_single_bit(unsigned-integer value); bool stdc_has_single_bit_uc(unsigned char value); bool stdc_has_single_bit_us(unsigned short value); bool stdc_has_single_bit_ui(unsigned int value); bool stdc_has_single_bit_ul(unsigned long value); bool stdc_has_single_bit_ull(unsigned long long value); These functions return true if there is exactly one 1 bit in value, or false otherwise. #include unsigned int stdc_bit_width(unsigned-integer value); unsigned int stdc_bit_width_uc(unsigned char value); unsigned int stdc_bit_width_us(unsigned short value); unsigned int stdc_bit_width_ui(unsigned int value); unsigned int stdc_bit_width_ul(unsigned long value); unsigned int stdc_bit_width_ull(unsigned long long value); These functions return the minimum width of unsigned integer that can hold the specified value. If value is 0, they return 0. #include unsigned-integer stdc_bit_floor(unsigned-integer value); unsigned char stdc_bit_floor_uc(unsigned char value); unsigned short stdc_bit_floor_us(unsigned short value); unsigned int stdc_bit_floor_ui(unsigned int value); unsigned long stdc_bit_floor_ul(unsigned long value); unsigned long long stdc_bit_floor_ull(unsigned long long value); These functions return the greatest power of two that is less than or equal to value. If value is 0, they return 0. #include unsigned-integer stdc_bit_ceil(unsigned-integer value); unsigned char stdc_bit_ceil_uc(unsigned char value); unsigned short stdc_bit_ceil_us(unsigned short value); unsigned int stdc_bit_ceil_ui(unsigned int value); unsigned long stdc_bit_ceil_ul(unsigned long value); unsigned long long stdc_bit_ceil_ull(unsigned long long value); These functions return the smallest power of two that is greater than or equal to value. If that number cannot be represented in the parameter type, they return 0. 21. The fetestexceptflag function has been added: #include int fetestexceptflag(const fexcept_t *flagp, int excepts); This function tests if certain floating-point exception flags are set in *flagp, which should have been previously set by a call to fegetexceptflag. The excepts argument is a bitwise OR of floating-point exception macros defined in , specifying the exception flags to test for. It must only include exception macros that were also included in the excepts argument to the fegetexceptflag call that set *flagp. fetestexceptflag returns the bitwise OR of the specified exceptions that are set in *flagp. 22. The fegetmode and fesetmode functions have been added: #include int fegetmode(femode_t *modep); int fesetmode(const femode_t *modep); The fegetmode function sets *modep to a representation of the currently-active floating-point control modes, which are dynamic settings that affect the behavior of floating-point operations. The fesetmode function sets the floating-point control modes to the values indicated by modep, which must either point to a value previously set by fegetmode or be the special macro value FE_DFL_MODE, which indicates the default control modes. These calls return 0 if they successfully carried out the operation, or non-zero otherwise. Under ORCA/C, they always succeed if given valid arguments. In ORCA/C, the floating-point control modes include the rounding direction, rounding precision, and halt-enable flags. See the Apple Numerics Manual for more information about these settings. -- Bugs from C 2.2.1 that have been fixed in C 2.3.0 ------------------------ 1. Constant expressions cast to _Bool, short, or unsigned short would not match the corresponding association in a generic selection expression. 2. A spurious error could be reported if the definition of a function returning a function pointer did not include names for the parameters of the pointed-to function type, e.g.: void (*f(void))(int, long) { /*...*/ } 3. Function parameters can now be declared with function types, which get automatically adjusted to function pointers. 4. If a prototype parameter list appeared as part of a type name (e.g. when type casting a function pointer), it would be ignored and treated as if no prototype was provided. 5. When the unary conversion rules (integer promotions) were applied to an expression of type unsigned short, the resulting type was sometimes unsigned short rather than unsigned int. This could affect _Generic expressions. 6. In certain circumstances where the value of a 16-bit signed integer variable was converted to a wider type following an earlier access to the 16-bit variable, negative values might not be converted correctly if native code peephole optimizations and register optimizations were both enabled. 7. Division or remainder operations with constant operands might be evaluated incorrectly if one operand was a negative integer and the other had an unsigned type, because the usual arithmetic conversions were not applied properly. 8. Spurious errors would be reported for some operations involving expressions of function type, including comparisons like *function_pointer == function_name. 9. Spurious errors would be reported if an enumeration constant defined in an inner scope had the same name as a typedef defined in an outer scope. 10. The scope of an enumeration constant should only begin after the full enumerator that defines it. Thus, within the expression giving the enumeration constant value (if present), any definition of the same enumeration constant name from an outer scope should still be visible and usable. Therefore, code like the following should work as indicated: enum {X = 123}; void f(void) { enum {X = X + 12}; /* X has the value 135 here */ } 11. The type of an expression using the , operator should be exactly that of its right operand, not subject to the unary conversion rules (integer promotions). 12. In the scanf() family of functions, if the input to an 'i' conversion was in hexadecimal format (starting with 0x or 0X), the next character after the number might be altered while processing that conversion. This might cause it not to properly match the next element of the scanf format string (if any), or might cause a subsequent input operation to read the wrong character. 13. In the strto(u)l, strto(u)ll, strtoimax, or strtoumax functions, if base is 0 or 16 and the numeric part of the string (after any leading white space and/or sign) starts with 0x or 0X but is not followed by a hexadecimal digit, only the 0 should be taken as part of the number. Thus, the result should be 0, errno should not be set (this is not an error), and if the second parameter (ptr) is non-null, *ptr should be set to point to the x or X. 14. The localtime() function might not set the tm_isdst field correctly in programs that use the large memory model. 15. The localtime(), gmtime(), and mktime() functions were unnecessarily slow. They are now significantly faster. 16. If a pointer to or array of a tagged struct or union type was declared in an outer scope and subsequently used in an inner scope where a different type had been declared with the same tag, a spurious error might be reported.