LoginSignup
0
0

7.6 Floating-point environment <fenv.h>, CN3054:2022 (17) p211.c

Last updated at Posted at 2022-11-20

7.5 Errors はソースコードが事実上なし。
7.7 Characteristics of floating types ソースコードなし 

はじめに(Introduction)

N3054 Working Draft, Standard for Programming Language C

C++ nは、ISO/IEC JTC1 SC22 WG14の作業原案(Working Draft)です。
公式のISO/IEC 9899原本ではありません。

ISO/IEC JTC1 SC22 のWG14を含むいくつかのWGでは、可能な限り作業文書を公開し、幅広い意見を求めています。

ISO/IEC JTC1 SC7からISO/IEC JTC1 SC22リエゾンとして、2000年頃、C/C++の品質向上に貢献しようとした活動をしていたことがあります。その頃は、まだISO/IEC TS 17961の原案が出る前です。Cの精神が優勢で、セキュリティ対策は補助的な位置付けでした。ISO/IEC TS 17961の制定と、C/C++のライブラリ類の見直しと、C++の進化はどんどん進んでいきます。 

進化の具合が、どちらに行こうとしているかは、コンパイルて実行させてみないとわかりません。C/C++の規格案の電子ファイルは、そのままコンパイルできる形式であるとよいと主張してきました。MISRA-C/C++, CERTC/C++でも同様です。MISRA-C/C++は、Example Suiteという形で、コード断片をコンパイルできる形で提供するようになりました。

一連の記事はコード断片をコンパイルできる形にする方法を検討してコンパイル、リンク、実行して、規格案の原文と処理系(gcc, clang)との違いを確認し、技術内容を検討し、ISO/IEC JTC1 SC22 WG21にフィードバックするために用います。
また、CERT C/C++, MISRA C/C++等のコーディング標準のコード断片をコンパイルする際の参考にさせていただこうと考えています。CERT C++, MISRA C++が標準化の動きとの時間的なずれがあれば確認できれば幸いです。また、boostライブラリとの関連、Linux OS, 箱庭プロジェクト、g++(GCC), clang++(LLVM)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。

最新規格はCN3096

<この項は書きかけです。順次追記します。>

背景(back ground)

C/C++でコンパイルエラーが出ると、途方にくれることがしばしばあります。
何回かに1回は、該当するエラーが検索できます。
ただ、条件が違っていて、そこでの修正方法では目的を達成しないこともしばしばです。いろいろな条件のコンパイルエラーとその対応方法について、広く記録することによって、いつか同じエラーに遭遇した時にやくに立つことを目指しています。

過去に何度か、自分のネットでの記録に助けられたことがあります。

また
https://researchmap.jp/joub9b3my-1797580/#_1797580
に記載したサイトのお世話になっています。

作業方針(sequence)

clangでは--std=c11, -std=C17 -std=c2xの3種類
gccでは-std=c11, -std=C17 -std=c2xの3種類
でコンパイルし、

1)コンパイルエラーを収集する。
2)コンパイルエラーをなくす方法を検討する。
コンパイルエラーになる例を示すだけが目的のコードは、コンパイルエラーをなくすのではなく、コンパイルエラーの種類を収集するだけにする。
文法を示すのが目的のコード場合に、コンパイルエラーをなくすのに手間がかかる場合は、順次作業します。
3)リンクエラーをなくす方法を検討する。
文法を示すのが目的のコード場合に、リンクエラーをなくすのに手間がかかる場合は、順次作業します。
4)意味のある出力を作る。
コンパイル、リンクが通っても、意味のある出力を示そうとすると、コンパイル・リンクエラーが出て収拾できそうにない場合がある。順次作業します。

1)だけのものから4)まで進んだものと色々ある状態です。一歩でも前に進むご助言をお待ちしています。「検討事項」の欄に現状を記録するようにしています。

bash
$ docker run -v /Users/ogawakiyoshi/n4910/n3540:/Users/ogawakiyoshi/n4910/n3540 -it kaizenjapan/n3540 /bin/bash

読書感想文

CコンパイラによるC言語規格の読書感想文として掲載しています。

コンパイル実験が、CN3242に対する、gccとclangによる感想文だということご理解いただけると幸いです。

読書感想文は人間かAIだけが作るものとは限りません。
本(電子書籍を含む)を入力として、その内容に対する文字列を読書感想文として受け止めましょう。
元の文章をあり方、コンパイルできるように電子化しておくこと、コンパイラが解釈可能な断片の作り方など。

個人開発

Cコンパイラの試験を一人でもくもくとやっているのは個人開発の一つの姿です。

<この項は書きかけです。順次追記します。>

編纂器(Compiler)

clang --version

Debian clang version 14.0.6-++20220622053050+f28c006a5895-1~exp1~20220622173135.152
Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin

gcc --version

gcc (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

7.6 Floating-point environment , CN3054:2022 (17) p211.c

算譜(source code)

p211.c
// CN3054 Committee Draft, Standard for Programming Language C
// http://www.open-std.org/jtc1/sc22/wg14/docs/papers/2022/n3054.pdf
const char * n3054 = "7.6 Floating-point environment <fenv.h>, CN3054:2022 (17) p211.c";
// Debian clang version 14.0.5-++20220610033153+c12386ae247c-
// g++ (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
// Edited by Dr. OGAWA Kiyoshi. Compile procedure and results record.
// C++N3054:2022 Standard Working Draft on ISO/IEC 14882(0) sample code compile list

#include "N3054.h"

// 7.6.1 The FENV_ACCESS pragma Synopsis
//  The FENV_ACCESS pragma provides a means to inform the implementation when a program might access the floating-point environment to test floating-point status flags or run under non-default floating-point control modes.263) The pragma shall occur either outside external declarations or preceding all explicit declarations and statements inside a compound statement. When outside external declarations, the pragma takes effect from its occurrence until another FENV_ACCESS pragma is encountered, or until the end of the translation unit. When inside a compound statement, the pragma takes effect from its occurrence until another FENV_ACCESS pragma is encountered (including within a nested compound statement), or until the end of the compound statement. At the end of a compound statement, the state for the pragma is restored to its condition just before the compound statement. If this pragma is used in any other context, the behavior is undefined. If part of a program tests floating-point status flags or establishes non-default floating-point mode settings using any means other than the FENV_ROUND pragmas, but was translated with the state for the FENV_ACCESS pragma "off", the behavior is undefined. The default state ("on" or "off") for the pragma is implementation-defined. (When execution passes from a part of the program translated with FENV_ACCESS "off" to a part translated with FENV_ACCESS "on", the state of the floating-point status flags is unspecified and the floating-point control modes have their default settings.)
//  EXAMPLE
// 262)See "future library directions" (7.33.4).
// 263)The purpose of the FENV_ACCESS pragma is to allow certain optimizations that could subvert flag tests and mode changes (e.g., global common subexpression elimination, code motion, and constant folding). In general, if the state of FENV_ACCESS is "off", the translator can assume that the flags are not tested, and that default modes are in effect, except where specified otherwise by an FENV_ROUND pragma.
//          Description
#include <fenv.h>
#pragma STDC FENV_ACCESS on-off-switch
#include <fenv.h>
void f(double x) {
}
#pragma STDC FENV_ACCESS ON
void g(double);
void h(double);
/* ... */
g(x + 1);
h(x + 1); /* ... */
//  If the function g might depend on status // flags set as a side effect of the first x + 1, or if the second x + 1might depend on control modes set as aside effect of the call to functiong, then the program has to contain an appropriately placed invocation of
#pragma STDC FENV_ACCESS ONasshown.264)
// 7.6.2 The FENV_ROUND pragma Synopsis
// The FENV_ROUND pragma provides a means to specify a constant rounding direction for floating-point operations for standard floating types within a translation unit or compound statement. The pragma shall occur either outside external declarations or before all explicit declarations and statements inside a compound statement. When outside external declarations, the pragma takes effect from its occurrence until another FENV_ROUND pragma is encountered, or until the end of the translation unit. When inside a compound statement, the pragma takes effect from its occurrence until another FENV_ROUND pragma is encountered (including within a nested compound statement), or until the end of the compound statement; at the end of a compound statement the static rounding mode is restored to its condition just before the compound statement. If this pragma is used in any other context, its behavior is undefined.
// direction shall be one of the names of the supported rounding direction macros for operations for standard floating types (7.6), or FE_DYNAMIC. If any other value is specified, the behavior is unde- fined. If no FENV_ROUND pragma is in effect, or the specified constant rounding mode is FE_DYNAMIC, rounding is according to the mode specified by the dynamic floating-point environment, which is the dynamic rounding mode that was established either at thread creation or by a call to fesetround, fesetmode, fesetenv, or feupdateenv. If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off", the translator may assume that the default rounding mode is in effect.
//  The FENV_ROUND pragma affects operations for standard floating types. Within the scope of an FENV_ROUND pragma establishing a mode other than FE_DYNAMIC, floating-point operators, implicit conversions (including the conversion of a value represented in a format wider than its semantic types to its semantic type, as done by classification macros), and invocations of functions indicated in the table below, for which macro replacement has not been suppressed (7.1.4), shall be evaluated according to the specified constant rounding mode (as though no constant mode was specified and the corresponding dynamic rounding mode had been established by a call to fesetround). Invocations of functions for which macro replacement has been suppressed and invocations of functions other than those indicated in the table below shall not be affected by constant rounding modes – they are affected by (and affect) only the dynamic mode. Floating constants (6.4.4.2) of a standard floating type that occur in the scope of a constant rounding mode shall be interpreted according to that mode.
// 264)The side effects impose a temporal ordering that requires two evaluations of x + 1. On the other hand, without the
#pragma STDC FENV_ACCESS ON
// pragma and assuming the default state is "off", just on e evaluation of x + 1 would suffice.
//         Description
#include <fenv.h>
#pragma STDC FENV_ROUND direction
#pragma STDC FENV_ROUND FE_DYNAMIC
//  Functions affected by constant rounding modes – for standard
// floating types
//    Header
//  Function families
//   <math.h>
//  acos, acospi, asin, asinpi, atan, atan2, atan2pi, atanpi
//   <math.h>
//  cos, cospi, sin, sinpi, tan, tanpi
//   <math.h>
//  acosh, asinh, atanh
//   <math.h>
//  cosh, sinh, tanh
//   <math.h>
//  exp, exp10, exp10m1, exp2, exp2m1, expm1
//   <math.h>
//  log, log10, log10p1, log1p, log2, log2p1, logp1
//   <math.h>
//  scalbn, scalbln, ldexp
//   <math.h>
//  cbrt, compoundn, hypot, pow, pown, powr, rootn, rsqrt, sqrt
//   <math.h>
//  erf, erfc
//   <math.h>
//  lgamma, tgamma
//   <math.h>
//  rint, nearbyint, lrint, llrint
//   <math.h>
//  fdim
//   <math.h>
//  fma
//   <math.h>
//  fadd, dadd, fsub, dsub, fmul, dmul, fdiv, ddiv, ffma, dfma, fsqrt, dsqrt
//  <stdlib.h>
//  atof, strfrom, strto
//   <wchar.h>
//  wcsto
//   <stdio.h>
//  printf and scanf families
//   <wchar.h>
//  wprintf and wscanf families
// A function family listed in the table above indicates the functions for all standard floating types, where the function family is represented by the name of the functions without a suffix. For example, acos indicates the functions acos, acosf, and acosl.
// NOTE 1 Constant rounding modes (other than FE_DYNAMIC) could be implemented using dynamic rounding modes as illustrated in the following example:
// where __swapround is defined by:
// 7.6.3 The FENV_DEC_ROUND pragma Synopsis
#include <fenv.h>
{
#pragma STDC FENV_ROUND direction // compiler inserts:
}
// #pragma STDC FENV_ACCESS ON
// int __savedrnd;
// __savedrnd = __swapround(direction);
//...  operations affected by constant rounding mode ...
// compiler inserts:
// __savedrnd = __swapround(__savedrnd);
//...  operations not affected by constant rounding mode ...
// compiler inserts:
// __savedrnd = __swapround(__savedrnd);
//...  operations affected by constant rounding mode ...
// compiler inserts:
// __swapround(__savedrnd);
static inline int __swapround(const int new) {
    const int old = fegetround();
    fesetround(new);
    return old;
}
#ifdef __STDC_IEC_60559_DFP__
#pragma STDC FENV_DEC_ROUND dec-direction
#endif
//               Description
//  The FENV_DEC_ROUND pragma is a decimal floating-point analog of the FENV_ROUND pragma. If FLT_RADIX is not 10, the FENV_DEC_ROUND pragma affects operators, functions, and floating con- stants only for decimal floating types. The affected functions are listed in the table below. If FLT_RADIX is 10, whether the FENV_ROUND and FENV_DEC_ROUND pragmas alter the rounding direc- tion of both standard and decimal floating-point operations is implementation-defined. dec-direction shall be one of the decimal rounding direction macro names (FE_DEC_DOWNWARD, FE_DEC_TONEAREST , FE_DEC_TONEARESTFROMZERO, FE_DEC_TOWARDZERO, and FE_DEC_UPWARD) defined in 7.6, to specify a constant rounding mode, or FE_DEC_DYNAMIC, to specify dynamic rounding. The corresponding dynamic rounding mode can be established by a call to fe_dec_setround.
// Functions affected by constant rounding modes – for decimal float- ing types
//   Header
//  Function families
//   <math.h>
//  acos, acospi, asin, asinpi, atan, atan2, atan2pi, atanpi
//   <math.h>
//  cos, cospi, sin, sinpi, tan, tanpi
//   <math.h>
//  acosh, asinh, atanh
//   <math.h>
//  cosh, sinh, tanh
//   <math.h>
//  exp, exp10, exp10m1, exp2, exp2m1, expm1
//   <math.h>
//  log, log10, log10p1, log1p, log2, log2p1, logp1
//   <math.h>
//  scalbn, scalbln, ldexp
//   <math.h>
//  cbrt, compoundn, hypot, pow, pown, powr, rootn, rsqrt, sqrt
//  <math.h>
//  erf, erfc
//   <math.h>
//  lgamma, tgamma
//   <math.h>
//  rint, nearbyint, lrint, llrint
//   <math.h>
//  quantize
//   <math.h>
//  fdim
//   <math.h>
//  fma
//   <math.h>
//  d32add, d64add, d32sub, d64sub, d32mul, d64mul, d32div, d64div, d32fma, d64fma, d32sqrt, d64sqrt
//   <stdlib.h>
//  strfrom, strto
//   <wchar.h>
//  wcsto
//   <stdio.h>
//  printf and scanf families
//   <wchar.h>
//  wprintf and wscanf families
//   A function family listed in the table above indicates the functions for all decimal floating types, where the function family is represented by the name of the functions without a suffix. For example, acos indicates the functions acosd32, acosd64, and acosd128.
// 7.6.4 Floating-point exceptions
//  The following functions provide access to the floating-point status flags.265) The int input argument for the functions represents a subset of floating-point exceptions, and can be zero or the bitwise ORofoneormorefloating-pointexceptionmacros,forexampleFE_OVERFLOW | FE_INEXACT.For other argument values, the behavior of these functions is undefined.
// 7.6.4.1 The feclearexcept function
// 265)The functions fetestexcept, feraiseexcept, and feclearexcept support the basic abstraction of flags that are either set or clear. An implementation can endow floating-point status flags with more information — for example, the address of the code which first raised the floating-point exception; the functions fegetexceptflag and fesetexceptflag deal with the full content of flags.
//  Synopsis
//  The feclearexcept function attempts to clear the supported floating-point exceptions represented by its argument.
// Returns
//  The feclearexcept function returns zero if the excepts argument is zero or if all the specified exceptions were successfully cleared. Otherwise, it returns a nonzero value.
// 7.6.4.2 The fegetexceptflag function Synopsis
//  The fegetexceptflag function attempts to store an implementation-defined representation of the states of the floating-point status flags indicated by the argument excepts in the object pointed to by the argument flagp.
// Returns
//  The fegetexceptflag function returns zero if the representation was successfully stored. Otherwise, it returns a nonzero value.
// 7.6.4.3 The feraiseexcept function Synopsis
// The feraiseexcept function attempts to raise the supported floating-point exceptions represented by its argument. 266) The order in which these floating-point exceptions are raised is unspecified, except as stated in F.8.6. Whether the feraiseexcept function additionally raises the "inexact" floating-point exception whenever it raises the "overflow" or "underflow" floating-point exception is implementation-defined.
// Returns
//  The feraiseexcept function returns zero if the excepts argument is zero or if all the specified exceptions were successfully raised. Otherwise, it returns a nonzero value.
// Recommended Practice
// Implementation extensions associated with raising a floating-point exception (for example, enabled traps or IEC 60559 alternate exception handling) should be honored by this function.
// 7.6.4.4 The fesetexcept function Synopsis
//  Description
//  Description
//  Description
#include <fenv.h>
int feclearexcept(int excepts);
#include <fenv.h>
int fegetexceptflag(fexcept_t *flagp, int excepts);
#include <fenv.h>
int feraiseexcept(int excepts);
#include <fenv.h>
int fesetexcept(int excepts);
// 266)The effect is intended to be similar to that of floating-point exceptions raised by arithmetic operations. Hence, implemen- tation extensions associated with raising a floating-point exception (for example, enabled traps or IEC 60559 alternate exception handling) should be honored. The specification in F.8.6 is in the same spirit.Description
//  The fesetexcept function attempts to set the supported floating-point exception flags represented by its argument. This function does not clear any floating-point exception flags. This function changes the state of the floating-point exception flags, but does not cause any other side effects that might be associated with raising floating-point exceptions. 267)
// Returns
//  The fesetexcept function returns zero if all the specified exceptions were successfully set or if the excepts argument is zero. Otherwise, it returns a nonzero value.
// 7.6.4.5 The fesetexceptflag function Synopsis
//  The fesetexceptflag function attempts to set the floating-point status flags indicated by the argument excepts to the states stored in the object pointed to by flagp. The value of *flagp shall have been set by a previous call to fegetexceptflag whose second argument represented at least those floating-point exceptions represented by the argument excepts. Like fesetexcept, this function does not raise floating-point exceptions, but only sets the state of the flags.
// Returns
//  The fesetexceptflag function returns zero if the excepts argument is zero or if all the specified flags were successfully set to the appropriate state. Otherwise, it returns a nonzero value.
// 7.6.4.6 The fetestexceptflag function Synopsis
//  The fetestexceptflag function determines which of a specified subset of the floating-point excep- tion flags are set in the object pointed to by flagp. The value of *flagp shall have been set by a previous call to fegetexceptflag whose second argument represented at least those floating-point exceptions represented by the argument excepts. The excepts argument specifies the floating-point status flags to be queried.
// Returns
//  The fetestexceptflag function returns the value of the bitwise OR of the floating-point exception macros included in excepts corresponding to the floating-point exceptions set in *flagp.
// 7.6.4.7 The fetestexcept function Synopsis
//  The fetestexcept function determines which of a specified subset of the floating-point excep- tion flags are currently set. The excepts argument specifies the floating-point status flags to be queried.268)
// 267)Implementation extensions like traps for floating-point exceptions and IEC 60559 exception handling do not occur. 268)This mechanism allows testing several floating-point exceptions with just one function call.
// Description
//  Description
// Description
#include <fenv.h>
int fesetexceptflag(const fexcept_t *flagp, int excepts);
#include <fenv.h>
int fetestexceptflag(const fexcept_t * flagp, int excepts);
#include <fenv.h>
int fetestexcept(int excepts);
// Returns
//  The fetestexcept function returns the value of the bitwise OR of the floating-point exception macros corresponding to the currently set floating-point exceptions included in excepts.
//  EXAMPLE Call f if "invalid" is set, then g if "overflow" is set:
#include <fenv.h> /* ... */
{
#pragma STDC FENV_ACCESS ON
    int set_excepts;
    feclearexcept(FE_INVALID | FE_OVERFLOW); // maybe raise exceptions
    set_excepts = fetestexcept(FE_INVALID | FE_OVERFLOW);
    if (set_excepts & FE_INVALID) f();
    if (set_excepts & FE_OVERFLOW) g();
    /* ... */
// 7.6.5 Rounding and other control modes
//  The fegetround and fesetround functions provide control of rounding direction modes. The fegetmode and fesetmode functions manage all the implementation’s dynamic floating-point control modes collectively.
// 7.6.5.1 The fegetmode function Synopsis
//  The fegetmode function attempts to store all the dynamic floating-point control modes in the object pointed to by modep.
// Returns
//  The fegetmode function returns zero if the modes were successfully stored. Otherwise, it returns a nonzero value.
// 7.6.5.2 The fegetround function Synopsis
//  The fegetround function gets the current value of the dynamic rounding direction mode. Returns
//  The fegetround function returns the value of the rounding direction macro representing the current dynamic rounding direction or a negative value if there is no such rounding direction macro or the current dynamic rounding direction is not determinable.
// 7.6.5.3 The fe_dec_getround function Synopsis
//  Description
//  Description
#include <fenv.h>
    int fegetmode(femode_t *modep);
#include <fenv.h>
    int fegetround(void);
#include <fenv.h>
#ifdef __STDC_IEC_60559_DFP__
    int fe_dec_getround(void);
#endif
// Description
//  The fe_dec_getround function gets the current value of the dynamic rounding direction mode for decimal floating-point operations.
// Returns
//  The fe_dec_getround function returns the value of the rounding direction macro representing the current dynamic rounding direction for decimal floating-point operations, or a negative value if there is no such rounding macro or the current rounding direction is not determinable.
// 7.6.5.4 The fesetmode function Synopsis
//  The fesetmode function attempts to establish the dynamic floating-point modes represented by the object pointed to by modep. The argument modep shall point to an object set by a call to fegetmode, or equal FE_DFL_MODE or a dynamic floating-point mode state macro defined by the implementation.
// Returns
// The fesetmode fesetmode function returns zero if the modes were successfully established. Other- wise, it returns a nonzero value.
// 7.6.5.5 The fesetround function Synopsis
//  The fesetround function establishes the rounding direction represented by its argument rnd. If the argument is not equal to the value of a rounding direction macro, the rounding direction is not changed.
// Returns
//  The fesetround function returns zero if and only if the dynamic rounding direction mode was set to the requested rounding direction.
// EXAMPLE Save, set, and restore the rounding direction. Report an error and abort if setting the rounding direction fails.
// Description
// Description
#include <fenv.h>
    int fesetmode(const femode_t *modep);
#include <fenv.h>
    int fesetround(int rnd);
#include <fenv.h>
#include <assert.h>
    void f(int rnd_dir) {
#pragma STDC FENV_ACCESS ON
        int save_round;
        int setround_ok;
        save_round = fegetround();
        setround_ok = fesetround(rnd_dir);
        assert(setround_ok == 0);
        /* ... */ fesetround(save_round); /* ... */
    }
// 7.6.5.6 The fe_dec_setround function Synopsis
//  The fe_dec_setround function sets the dynamic rounding direction mode for decimal floating- point operations to be the rounding direction represented by its argument rnd. If the argument is not equal to the value of a decimal rounding direction macro, the rounding direction is not changed.
//  If FLT_RADIX is not 10, the rounding direction altered by the fesetround function is independent of the rounding direction altered by the fe_dec_setround function; otherwise if FLT_RADIX is 10, whether the fesetround and fe_dec_setround functions alter the rounding direction of both standard and decimal floating-point operations is implementation-defined.
// Returns
// The fe_dec_setround function returns a zero value if and only if the argument is equal to a decimal rounding direction macro (that is, if and only if the dynamic rounding direction mode for decimal floating-point operations was set to the requested rounding direction).
// 7.6.6 Environment
//  The functions in this section manage the floating-point environment // — status flags and control modes — as one entity.
// 7.6.6.1 The fegetenv function Synopsis
//  The fegetenv function attempts to store the current dynamic floating-point environment in the object pointed to by envp.
// Returns
//  The fegetenv function returns zero if the environment was successfully stored. Otherwise, it returns a nonzero value.
// 7.6.6.2 The feholdexcept function Synopsis
//  The feholdexcept function saves the current dynamic floating-point environment in the object pointed to by envp, clears the floating-point status flags, and then installs a non-stop (continue on floating-point exceptions) mode, if available, for all floating-point exceptions.269)
// 269)IEC 60559 systems have a default non-stop mode, and typically at least one other mode for trap handling or aborting; if the system provides only the non-stop mode then installing it is trivial. For such systems, the feholdexcept function can be used in conjunction with the feupdateenv function to write routines that hide spurious floating-point exceptions from their callers.
#include <fenv.h>
#ifdef __STDC_IEC_60559_DFP__
    int fe_dec_setround(int rnd);
#endif
//  Description
//  Description
// Description
#include <fenv.h>
    int fegetenv(fenv_t *envp);
#include <fenv.h>
    int feholdexcept(fenv_t *envp);
//  Returns
//  The feholdexcept function returns zero if and only if non-stop floating-point exception handling was successfully installed.
// 7.6.6.3 The fesetenv function Synopsis
//  The fesetenv function attempts to establish the dynamic floating-point environment represented by the object pointed to by envp. The argument envp shall point to an object set by a call to fegetenv or feholdexcept, or equal a dynamic floating-point environment macro. Note that fesetenv merely installs the state of the floating-point status flags represented through its argument, and does not raise these floating-point exceptions.
// Returns
//  The fesetenv function returns zero if the environment was successfully established. Otherwise, it returns a nonzero value.
// 7.6.6.4 The feupdateenv function Synopsis
//  The feupdateenv function attempts to save the currently raised floating-point exceptions in its automatic storage, install the dynamic floating-point environment represented by the object pointed to by envp, and then raise the saved floating-point exceptions. The argument envp shall point to an object set by a call to feholdexcept or fegetenv, or equal a dynamic floating-point environment macro.
// Returns
//  The feupdateenv function returns zero if all the actions were successfully carried out. Otherwise, it returns a nonzero value.
//  EXAMPLE Hide spurious underflow floating-point exceptions:
#include <fenv.h>
    double f(double x) {
//  Description
// Description
#include <fenv.h>
        int fesetenv(const fenv_t *envp);
#include <fenv.h>
        int feupdateenv(const fenv_t *envp);
    }
    int main() {
//    PR3(st.a,st.b,st.c,d);
        printf("%s\n", n3054);
        return EXIT_SUCCESS;
    }

編纂・実行結果(compile and go)

bash

$ clang p211.c -std=11 -o p211l -I. -Wall
p211.c:18:26: warning: expected 'ON' or 'OFF' or 'DEFAULT' in pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS on-off-switch
                         ^
p211.c:26:3: error: unknown type name 'x'
g(x + 1); h(x + 1); /* ... */
  ^
p211.c:26:5: error: expected ')'
g(x + 1); h(x + 1); /* ... */
    ^
p211.c:26:2: note: to match this '('
g(x + 1); h(x + 1); /* ... */
 ^
p211.c:26:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
g(x + 1); h(x + 1); /* ... */
^
p211.c:26:13: error: unknown type name 'x'
g(x + 1); h(x + 1); /* ... */
            ^
p211.c:26:15: error: expected ')'
g(x + 1); h(x + 1); /* ... */
              ^
p211.c:26:12: note: to match this '('
g(x + 1); h(x + 1); /* ... */
           ^
p211.c:26:11: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
g(x + 1); h(x + 1); /* ... */
          ^
p211.c:28:26: warning: expected 'ON' or 'OFF' or 'DEFAULT' in pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS ONasshown.264)
                         ^
p211.c:38:25: warning: invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored [-Wignored-pragmas]
#pragma STDC FENV_ROUND direction 
                        ^
p211.c:39:35: warning: pragma STDC FENV_ROUND is not supported [-Wunknown-pragmas]
#pragma STDC FENV_ROUND FE_DYNAMIC
                                  ^
p211.c:85:1: error: expected identifier or '('
{
^
p211.c:86:25: warning: invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored [-Wignored-pragmas]
#pragma STDC FENV_ROUND direction // compiler inserts:
                        ^
p211.c:210:1: error: expected identifier or '('
{
^
7 warnings and 6 errors generated.

$ clang p211.c -std=17 -o p211l -I. -Wall
p211.c:18:26: warning: expected 'ON' or 'OFF' or 'DEFAULT' in pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS on-off-switch
                         ^
p211.c:26:3: error: unknown type name 'x'
g(x + 1); h(x + 1); /* ... */
  ^
p211.c:26:5: error: expected ')'
g(x + 1); h(x + 1); /* ... */
    ^
p211.c:26:2: note: to match this '('
g(x + 1); h(x + 1); /* ... */
 ^
p211.c:26:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
g(x + 1); h(x + 1); /* ... */
^
p211.c:26:13: error: unknown type name 'x'
g(x + 1); h(x + 1); /* ... */
            ^
p211.c:26:15: error: expected ')'
g(x + 1); h(x + 1); /* ... */
              ^
p211.c:26:12: note: to match this '('
g(x + 1); h(x + 1); /* ... */
           ^
p211.c:26:11: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
g(x + 1); h(x + 1); /* ... */
          ^
p211.c:28:26: warning: expected 'ON' or 'OFF' or 'DEFAULT' in pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS ONasshown.264)
                         ^
p211.c:38:25: warning: invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored [-Wignored-pragmas]
#pragma STDC FENV_ROUND direction 
                        ^
p211.c:39:35: warning: pragma STDC FENV_ROUND is not supported [-Wunknown-pragmas]
#pragma STDC FENV_ROUND FE_DYNAMIC
                                  ^
p211.c:85:1: error: expected identifier or '('
{
^
p211.c:86:25: warning: invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored [-Wignored-pragmas]
#pragma STDC FENV_ROUND direction // compiler inserts:
                        ^
p211.c:210:1: error: expected identifier or '('
{
^
7 warnings and 6 errors generated.

$ clang p211.c -std=2x -o p211l -I. -Wall
p211.c:18:26: warning: expected 'ON' or 'OFF' or 'DEFAULT' in pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS on-off-switch
                         ^
p211.c:26:3: error: unknown type name 'x'
g(x + 1); h(x + 1); /* ... */
  ^
p211.c:26:5: error: expected ')'
g(x + 1); h(x + 1); /* ... */
    ^
p211.c:26:2: note: to match this '('
g(x + 1); h(x + 1); /* ... */
 ^
p211.c:26:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
g(x + 1); h(x + 1); /* ... */
^
p211.c:26:13: error: unknown type name 'x'
g(x + 1); h(x + 1); /* ... */
            ^
p211.c:26:15: error: expected ')'
g(x + 1); h(x + 1); /* ... */
              ^
p211.c:26:12: note: to match this '('
g(x + 1); h(x + 1); /* ... */
           ^
p211.c:26:11: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
g(x + 1); h(x + 1); /* ... */
          ^
p211.c:28:26: warning: expected 'ON' or 'OFF' or 'DEFAULT' in pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS ONasshown.264)
                         ^
p211.c:38:25: warning: invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored [-Wignored-pragmas]
#pragma STDC FENV_ROUND direction 
                        ^
p211.c:39:35: warning: pragma STDC FENV_ROUND is not supported [-Wunknown-pragmas]
#pragma STDC FENV_ROUND FE_DYNAMIC
                                  ^
p211.c:85:1: error: expected identifier or '('
{
^
p211.c:86:25: warning: invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored [-Wignored-pragmas]
#pragma STDC FENV_ROUND direction // compiler inserts:
                        ^
p211.c:210:1: error: expected identifier or '('
{
^
7 warnings and 6 errors generated.

$ gcc p211.c -std=11 -o p211g -I. -Wall
p211.c:18: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   18 | #pragma STDC FENV_ACCESS on-off-switch
      | 
p211.c:22: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   22 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:26:4: error: expected ')' before '+' token
   26 | g(x + 1); h(x + 1); /* ... */
      |    ^~
      |    )
p211.c:26:14: error: expected ')' before '+' token
   26 | g(x + 1); h(x + 1); /* ... */
      |              ^~
      |              )
p211.c:28: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   28 | #pragma STDC FENV_ACCESS ONasshown.264)
      | 
p211.c:34: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   34 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:38: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   38 | #pragma STDC FENV_ROUND direction
      | 
p211.c:39: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   39 | #pragma STDC FENV_ROUND FE_DYNAMIC
      | 
p211.c:85:1: error: expected identifier or '(' before '{' token
   85 | {
      | ^
p211.c:86: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   86 | #pragma STDC FENV_ROUND direction // compiler inserts:
      | 
p211.c:210:1: error: expected identifier or '(' before '{' token
  210 | {
      | ^
p211.c:211: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
  211 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:259: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
  259 | #pragma STDC FENV_ACCESS ON
      | 

$ gcc p211.c -std=c17 -o p211g -I. -Wall
p211.c:18: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   18 | #pragma STDC FENV_ACCESS on-off-switch
      | 
p211.c:22: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   22 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:26:4: error: expected ')' before '+' token
   26 | g(x + 1); h(x + 1); /* ... */
      |    ^~
      |    )
p211.c:26:14: error: expected ')' before '+' token
   26 | g(x + 1); h(x + 1); /* ... */
      |              ^~
      |              )
p211.c:28: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   28 | #pragma STDC FENV_ACCESS ONasshown.264)
      | 
p211.c:34: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   34 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:38: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   38 | #pragma STDC FENV_ROUND direction
      | 
p211.c:39: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   39 | #pragma STDC FENV_ROUND FE_DYNAMIC
      | 
p211.c:85:1: error: expected identifier or '(' before '{' token
   85 | {
      | ^
p211.c:86: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   86 | #pragma STDC FENV_ROUND direction // compiler inserts:
      | 
p211.c:210:1: error: expected identifier or '(' before '{' token
  210 | {
      | ^
p211.c:211: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
  211 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:259: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
  259 | #pragma STDC FENV_ACCESS ON
      | 

$ gcc p211.c -std=c2x -o p211g -I. -Wall
p211.c:18: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   18 | #pragma STDC FENV_ACCESS on-off-switch
      | 
p211.c:22: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   22 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:26:4: error: expected ')' before '+' token
   26 | g(x + 1); h(x + 1); /* ... */
      |    ^~
      |    )
p211.c:26:14: error: expected ')' before '+' token
   26 | g(x + 1); h(x + 1); /* ... */
      |              ^~
      |              )
p211.c:28: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   28 | #pragma STDC FENV_ACCESS ONasshown.264)
      | 
p211.c:34: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
   34 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:38: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   38 | #pragma STDC FENV_ROUND direction
      | 
p211.c:39: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   39 | #pragma STDC FENV_ROUND FE_DYNAMIC
      | 
p211.c:85:1: error: expected identifier or '(' before '{' token
   85 | {
      | ^
p211.c:86: warning: ignoring '#pragma STDC FENV_ROUND' [-Wunknown-pragmas]
   86 | #pragma STDC FENV_ROUND direction // compiler inserts:
      | 
p211.c:210:1: error: expected identifier or '(' before '{' token
  210 | {
      | ^
p211.c:211: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
  211 | #pragma STDC FENV_ACCESS ON
      | 
p211.c:259: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
  259 | #pragma STDC FENV_ACCESS ON
      | 

検討事項(agenda)

コンパイルエラーを取るか、コンパイルエラーの理由を解説する。

応用例1 MISRA C/C++

MISRA C まとめ #include

MISRA C++ 5-0-16

応用例2 CERT C/C++

SEI CERT C++ Coding Standard AA. Bibliography 確認中。

MISRA C/C++, AUTOSAR C++, CERT C/C++とC/C++工業標準をコンパイルする

自己参考資料(self reference)

関連する自己参照以外は、こちらの先頭に移転。

C言語(C++)に対する誤解、曲解、無理解、爽快。

C2011コンパイル一覧@researchmap

https://researchmap.jp/jownvh0ye-1797580/#_1797580

[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。

C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識

dockerにclang

docker gnu(gcc/g++) and llvm(clang/clang++)

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)

astyle 使ってみた

<この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。>

文書履歴(document history)

ver. 0.01 初稿  20221120
ver. 0.02 ありがとう追記 20230622

最後までおよみいただきありがとうございました。

いいね 💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚 and follow me for your happy life.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0