*/ } ul /* Whole unordered list */ { } ul li /* Unordered list item */ { } ol /* Whole ordered list */ { } ol li /* Ordered list item */ { } hr {} /* ---- Some span elements --- */ sub /* Subscripts. Pandoc: H~2~O */ { } sup /* Superscripts. Pandoc: The 2^nd^ try. */ { } em /* Emphasis. Markdown: *emphasis* or _emphasis_ */ { } em > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } /* ---- Links (anchors) ---- */ a /* All links */ { /* Keep links clean. On screen, they are colored; in print, they do nothing anyway. */ text-decoration: none; } @media screen { a:hover { /* On hover, we indicate a bit more that it is a link. */ text-decoration: underline; } } @media print { a { /* In print, a colored link is useless, so un-style it. */ color: black; background: transparent; } a[href^="http://"]:after, a[href^="https://"]:after { /* However, links that go somewhere else, might be useful to the reader, so for http and https links, print the URL after what was the link text in parens */ content: " (" attr(href) ") "; font-size: 90%; } } /* ---- Images ---- */ img { /* Let it be inline left/right where it wants to be, but verticality make it in the middle to look nicer, but opinions differ, and if in a multi-line paragraph, it might not be so great. */ vertical-align: middle; } div.figure /* Pandoc figure-style image */ { /* Center the image and caption */ margin-left: auto; margin-right: auto; text-align: center; font-style: italic; } p.caption /* Pandoc figure-style caption within div.figure */ { /* Inherits div.figure props by default */ } /* ---- Code blocks and spans ---- */ pre, code { background-color: #fdf7ee; /* BEGIN word wrap */ /* Need all the following to word wrap instead of scroll box */ /* This will override the overflow:auto if present */ white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ /* END word wrap */ } pre /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.5em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 1px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.5em; margin-right: 0.5em; } pre.yacc, code.yacc { background-color: #f0f0f0; } pre.yacc /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.0em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 0px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.0em; margin-right: 0.0em; } @media screen { pre { white-space: pre; /* Dotted looks better on screen and solid seems to print better. */ border: 1px dotted #777; } } code /* All inline code spans */ { } p > code, li > code /* Code spans in paragraphs and tight lists */ { /* Pad a little from adjacent text */ padding-left: 2px; padding-right: 2px; } li > p code /* Code span in a loose list */ { /* We have room for some more background color above and below */ padding: 2px; } span.option { color: blue; text-decoration: underline; } /* ---- Math ---- */ span.math /* Pandoc inline math default and --jsmath inline math */ { /* Tried font-style:italic here, and it messed up MathJax rendering in some browsers. Maybe don't mess with at all. */ } div.math /* Pandoc --jsmath display math */ { } span.LaTeX /* Pandoc --latexmathml math */ { } eq /* Pandoc --gladtex math */ { } /* ---- Tables ---- */ /* A clean textbook-like style with horizontal lines above and below and under the header. Rows highlight on hover to help scanning the table on screen. */ table { border-collapse: collapse; border-spacing: 0; /* IE 6 */ border-bottom: 2pt solid #000; border-top: 2pt solid #000; /* The caption on top will not have a bottom-border */ /* Center */ margin-left: auto; margin-right: auto; } thead /* Entire table header */ { border-bottom: 1pt solid #000; background-color: #eee; /* Does this BG print well? */ } tr.header /* Each header row */ { } tbody /* Entire table body */ { } /* Table body rows */ tr { } tr.odd:hover, tr.even:hover /* Use .odd and .even classes to avoid styling rows in other tables */ { background-color: #eee; } /* Odd and even rows */ tr.odd {} tr.even {} td, th /* Table cells and table header cells */ { vertical-align: top; /* Word */ vertical-align: baseline; /* Others */ padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; padding-bottom: 0.2em; } /* Removes padding on left and right of table for a tight look. Good if thead has no background color*/ /* tr td:last-child, tr th:last-child { padding-right: 0; } tr td:first-child, tr th:first-child { padding-left: 0; } */ th /* Table header cells */ { font-weight: bold; } tfoot /* Table footer (what appears here if caption is on top?) */ { } caption /* This is for a table caption tag, not the p.caption Pandoc uses in a div.figure */ { caption-side: top; border: none; font-size: 0.9em; font-style: italic; text-align: center; margin-bottom: 0.3em; /* Good for when on top */ padding-bottom: 0.2em; } /* ---- Definition lists ---- */ dl /* The whole list */ { border-top: 2pt solid black; padding-top: 0.5em; border-bottom: 2pt solid black; } dt /* Definition term */ { font-weight: bold; } dd+dt /* 2nd or greater term in the list */ { border-top: 1pt solid black; padding-top: 0.5em; } dd /* A definition */ { margin-bottom: 0.5em; } dd+dd /* 2nd or greater definition of a term */ { border-top: 1px solid black; /* To separate multiple definitions */ } /* ---- Footnotes ---- */ a.footnote, a.footnoteRef { /* Pandoc, MultiMarkdown footnote links */ font-size: small; vertical-align: text-top; } a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown, ?? footnote back links */ { } @media print { a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown */ { /* Don't display these at all in print since the arrow is only something to click on */ display: none; } } div.footnotes /* Pandoc footnotes div at end of the document */ { } div.footnotes li[id^="fn"] /* A footnote item within that div */ { } table tr td,th { border-right: 1px solid; border-left: 1px solid; } /* You can class stuff as "noprint" to not print. Useful since you can't set this media conditional inside an HTML element's style attribute (I think), and you don't want to make another stylesheet that imports this one and adds a class just to do this. */ @media print { .noprint { display:none; } }
2025-04-29
integration into IS ISO/IEC 9899:202y
document number | date | comment |
---|---|---|
n3543 | 202504 | this document |
Generic features to compute minimum and maximum value of two given values is notoriously challenging in C.
fmin
tg macro of <tgmath.h>
)
may result in loss of precision.We propose to add type-generic macros that solve all these problems. Namely:
In particular the choice for the minimum differs from the usual
arithmetic conversions. If one type is signed and the other is unsigned
the macro ckd_min
chooses the signed
type for the result.
Possible problems arise
For these cases we propose different variants, one that rejects translation in these cases, one that makes these cases implementation-defined, including the possibility to reject translation, and one that has undefined behavior.
For convenience, we propose to add the features to the <stdckdint.h>
header with the idea this header contains operations that are merely
language features that always have defined behavior. The suggested
wording could easily be adapted to be placed in a different header
(clause 7) or even to be introduced as proper operators (clause 6).
Implementations of minimum and maximum functions there are plenty. Even the current C standard provides a handful of slightly different interfaces, even for type-generic ones. Then, in the field an abundant number of implementations of varying properties and quality are added to that picture.
We are not aware of an implementation of these functionalities that
all the problems that are listed in the introduction. In particular,
none of them seems to provide an integer constant expression where this
would be possible. This is all the more surprising as that property has
a clear demand (in particular for array lengths) and as providing macros
that have that property is not too difficult by using either
implementation-specific extensions (such as gcc’s __builtin_constant_p
) and/or playing tricks
with _Generic
.
The goal of this paper is to propose a unification to all these interfaces and their behavior, such that programmers find reliable implementations of these features in their C library. The reference implementation that we maintain (and are able to provide on request) is not meant to suggest any particular way in which these features should be implemented, but only to prove that an implementation is possible as of today with minimal effort.
In 7.20.1, bump the value of __STDC_VERSION_STDCKDINT_H__
.
Then add a new clause
7.20.4 Minimum and maximum operation type-generic macros
Synopsis
#include <stdckdint.h>
(typeA a, typeB b);
minType ckd_min(typeA a, typeB b); maxType ckd_max
Description
2 These type-generic macros compute the minimum and maximum value of their arguments, respectively. If both arguments are integer constant expressions, the macro call expression is also an integer constant expressions.
3 The result typemaxType
istypeof(a+b)
. The result typeminType
is determined as follows:
- If
maxType
is an unsigned integer type and if one oftypeA
ortypeB
has negative values,minType
istypeof(+a)
ortypeof(+b)
, respectively.
- Otherwise,
minType
is the same asmaxType
.
Returns
4 If none of the arguments is a NaN, the result of the operation is the mathematically lesser (respectively greater) argument converted to typeminType
andmaxType
, respectively. Otherwise, if one of the arguments is a signaling NaN, the “domain error” floating point exception is raised and the result is a signaling NaN of the appropriate type. Otherwise, if one of the arguments is a quiet NaN, no floating point exception is raised and the result is a quiet NaN of the appropriate type.
5 NOTE 1 If both arguments have integer type,
minType
andmaxType
are able to represent the mathematical result of the respective operation.
6 NOTE 2 For other type combinations (e.g combining auint64_t
integer and an ISO/IEC 60559 binary64 floating point type) the typesminType
andmaxType
(here the floating point type) is not able to hold the precise result of the operations for all possible combinations of argument values.
7 Example
#include <ckdint.h>
constexpr size_t n = SIZE_MAX;
static double A[ckd_max(n, 1)]; // valid
constexpr auto ms = ckd_min(n, 0); // valid, type is int
constexpr auto mu = ckd_min(n, 0u); // valid, type is size_t
constexpr auto mc = ckd_min(n, (char)0); // valid, type depends on architecture
constexpr auto md = ckd_min(n, 0.0); // type double, possibly invalid
Here, the array length expression ofA
computes the maximum of two integer constant expressions and is thus an integer constant expression, too. Forms
, one of the arguments tockd_min
has a signed type, so the result type is that signed type. Conversely, formu
both arguments have an unsigned type, and so the result is the common real type. The type ofmc
depends on whether or notchar
admits negative values; if so, the result type isint
, otherwise it issize_t
. Formd
the common real type isdouble
, but it is implementation-defined if the value ofSIZE_MAX
is representable without loss of precision in that type.
It is important to add the possibility to reject combinations that cannot properly represent the mathematical result in all cases. Therefore one of the following variants should be added to the text above.
Add to 7.20.4 as described above
3′ IftypeA
andtypeB
do not have a common real type or if the result type of the operation is not able to hold the result for all possible value combinations oftypeA
andtypeB
, the program translation fails.
Add to the end of 7.20.4 p7 (example) as described above
If it is, all possible value combinations of values are representable in
the result and the definition of md
is
accepted; otherwise the program translation fails.
Add to J .3.16, architecture specific behavior
- If calls to the
ckd_min
andckd_max
type-generic macros with certain combinations of integer and floating arguments are accepted (7.20.4).
Add to 7.20.4 as described above
3′ IftypeA
andtypeB
do not have a common real type it is implementation-defined if the program translation fails or if the typesminType
andmaxType
are chosen in an implementation-defined way. If the result type of the operation is not able to hold the result for all possible value combinations oftypeA
andtypeB
, it is implementation-defined if the operation is accepted, possibly resulting in a loss of precision, or if the program translation fails.
Add to the end of 7.20.4 p7 (example) as described above
If it is, the definition ofmd
is accepted. Otherwise it is implementation-defined if the program translation fails or ifmd
has the value(double)SIZE_MAX
.
Add to J .3.15, implementation-defined behavior
- The behavior of calls to the
ckd_min
andckd_max
type-generic macros if their arguments do not have a common real type or if the result type cannot represent all possible results (7.20.4).
Add to 7.20.4 as described above
3′ IftypeA
andtypeB
do not have a common real type or if the result type of the operation is not able to hold the result for all possible value combinations oftypeA
andtypeB
, the behavior is undefined.
Add to the end of 7.20.4 p7 (example) as described above
If it is, the definition of md
is
valid, otherwise the behavior is undefined.
Add to J .2, undefined behavior
- The behavior of calls to the
ckd_min
andckd_max
type-generic macros if their arguments do not have a common real type or if the result type cannot represent all possible results (7.20.4).