標準Cにおいて、文字列から浮動小数点への変換エラーを検出するポータブルな方法は存在しない

2026/10/11 0:39

標準Cにおいて、文字列から浮動小数点への変換エラーを検出するポータブルな方法は存在しない

RSS: https://news.ycombinator.com/rss

要約▶

日本語翻訳:

既存の要約は明確、正確かつ簡潔であり、改善の余地はありません。

テキストに翻訳する

(必要に応じて;そうでなければ原文を繰り返す):既存の要約は明確、正確かつ簡潔であり、改善の余地はありません。

本文

strtod
などの文字列変換関数におけるエラー処理の仕組みと実装依存性

この記事は、数学関数のエラー処理マクロ

math_errhandling
および C 標準規格と POSIX の規定を補完する続編です。文字列から浮動小数点数への変換を行う一連の関数(
strtod
など)のエラー検出方法について解説します。

対象となる関数群

math.h
に含まれていないが、同様に
math_errhandling
の影響を受ける変換関数は以下の通りです。

  • strtod
  • strtof
  • strtold
  • strtod32
  • strtod64
  • strtod128

C 標準規格(7.25.2.6p12)での規定と実装依存性

規格では、オーバーフローやアンダーフロー時の挙動について以下のように記述されています。

オーバーフロー時

  • 返値:
    HUGE_VAL
    ,
    HUGE_VALF
    , または
    HUGE_VALL
    を返します(符号に依存)。
  • エラー報告条件:
    • math_errhandling & MATH_ERRNO
      が真の場合:整数式
      errno
      は
      ERANGE
      に設定される。
    • math_errhandling & MATH_ERREXCEPT
      が真の場合:浮動小数点例外として「オーバーフロー」が発生する。

アンダーフロー時

  • 返値: 最小正規化された正の数の絶対値以上にならないような値を返す。
  • エラー報告条件(実装依存):
    • math_errhandling & MATH_ERRNO
      が真の場合:
      errno
      を
      ERANGE
      に設定するかどうかは実装依存。
    • math_errhandling & MATH_ERREXCEPT
      が真の場合:「アンダーフロー」という例外が発生するかどうかは実装依存。

規格の意図と注意点

  • musl 等のケース:
    math_errhandling
    が
    errno
    のサポートを表明していない実装では、エラー時に
    errno
    は設定されません。
  • アンダーフロー報告義務なし: アンダーフロー時でもエラー報告が義務付けられていない点に注意が必要です。

POSIX 規格との違いと矛盾点

POSIX 規格は C 標準よりも厳格な要件を課しており、

math_errhandling
に配慮していません。

POSIX の規定(過剰指定)

  • オーバーフローまたはアンダーフロー発生時:必ず
    errno
    を
    [ERANGE]
    に設定する。
  • この振る舞いは C 標準の「実装依存」という旨意に反しています。

man ページとの矛盾

Linux の man ページ(

strtod(3)
)はこの拡張機能は一切言及していません。これは POSIX の規定が文書化されていないためです。

errno
に関する規格条文(7.12.2p8, 7.5p3)との整合性

  • 7.12.2p8:
    math_errhandling & MATH_ERRNO
    がゼロの場合、
    errno
    は設定されるか変更されない。
  • 7.5p3: 関数の説明で
    errno
    の使用が言及されていない場合は例外となる。

矛盾の所在:

  • strtod
    の説明には
    errno
    の使用が言及されています(ただし
    math_errhandling
    を条件としていません)。
  • これにより、POSIX の「常に
    ERANGE
    を設定する」という振る舞いは C 標準に準拠していない可能性が高まります。
  • 実態の例:
    • glibc: エラー時であっても
      errno
      を
      EINVAL
      に決して設定しない(返値は
      0
      )。
    • musl: 変換不可能な場合、
      errno
      を
      EINVAL
      に設定する。
    • 結論: man ページ上では文書化されていませんが、実装によって結果が異なります。

エラー検出の「正しい」アプローチ

規格の記述が不明瞭であり、

errno
だけでエラーを検出するのは非移植的です。以下にカテゴリ別に推奨される手法をまとめます。

1. オーバーフローの検出

POSIX をターゲットとする場合

  • errno
    の信頼度が高いため、シンプルにチェックします。
    errno = 0; // 呼び出し前のクリーンアップ
    double x = strtod(s, nullptr);
    bool overflow = (copysign(x, 1.0) == HUGE_VAL) && (errno == ERANGE);
    

それ以外(C 標準準拠)の場合

  • math_errhandling
    に従って検出メカニズムを判定する必要があります。
    errno = 0;
    feclearexcept(FE_OVERFLOW); // フラグをクリアする
    double x = strtod(s, nullptr);
    
    if (copysign(x, 1.0) == HUGE_VAL) {
        bool errored;
        if (math_errhandling & MATH_ERRNO) {
            errored = (errno == ERANGE);
        } else {
            // FENV_ACCESS を有効化しているか確認する(#pragma やコンパイラフラグ)
            errored = fetestexcept(FE_OVERFLOW);
        }
    }
    
  • 注意:
    feclearexcept
    /
    fetestexcept
    を使用する際は、コンパイラ設定(GCC:
    -ftrapping-math
    または
    #pragma STDC FENV_ACCESS ON
    )が必要な場合があります。

2. アンダーフローの検出

POSIX をターゲットとする場合

  • 値がゼロであり且つ
    errno
    が
    ERANGE
    の場合に検出します。単に
    errno > 0
    とだけチェックすると非移植的です。
    errno = 0;
    double x = strtod(s, nullptr);
    bool underflow = (x == 0.0) && (errno == ERANGE);
    

それ以外の場合

  • 実装がアンダーフローを報告しているか事前に確認する必要があります(多くの場合、文書化されていないため困難)。
  • SOL (Solution):
    libc
    の関数ではチェックできず、入力文字列自体を確認する必要がある場合があります。
    // アンダーフローが発生したと推測される場合(例:結果が 0.0)
    // 入力文字列の指数部以前に非ゼロの数字があるかを手動で確認し境界条件をチェック
    if (result == 0.0) {
       // 入力文字列 "1e-500" のようなパターンを検出するロジックが必要
    }
    

3. 無効な入力(変換なし)の検出

errno
は信頼できません。必ず第 2 引数
endptr
を使用し、ポインタが移動していないかチェックします。

char *endptr;
double x = strtod(s, &endptr);

if (endptr == s) {
    // 何も解析されなかった(入力文字列が無効または空)
} else {
    // 変換が成功した
    // ※この時点で errno はエラーコードではなく、範囲外エラーなどを含みうるため注意
}

まとめ

  • math_errhandling
    :
    math.h
    の数学関数でエラーハンドリング機構(
    errno
    vs 例外)を示すマクロ。
  • 変換関数の特殊性:
    strtod
    群は
    math_errhandling
    に依存せず、実装ごとに挙動が異なる可能性が高い。
  • POSIX の限界: POSIX は常に
    errno
    を設定すると規定するが、glibc など多くの実装ではこれを無視している。
  • 推奨事項: 最大限の可搬性を確保するには、オーバーフロー/アンダーフローは例外/API 仕様を、無効入力 (
    strtod
    ) は
    endptr
    を用いて検出することを徹底してください。

同じ日のほかのニュース

一覧に戻る →

2026/10/13 6:40

AI は道具です。それを巧みに使うには技術が必要です。

## 日本語翻訳: 本稿の核心的な論点は、大規模言語モデルは自律的な「自動化」ではなく、人間の技量が必要なツールであるというものである。これは、AI が独立した意思あるいは悪意を持って行動するという考え方を否定するものであり、ソフトウェアが「反逆する(rogue)」ように振る舞うなど、業界特有の成り行きや陰謀論的なナラティブに煽られておりやすい。物理的な器具が悪用され得るように、LLM もエンジニアリング上の制限によって予期せぬ出力を生み出すに過ぎず、エージェント性の喪失によるものではない。人間による判断が依然として中核をなすのは、ユーザーが盲目的に制御権を委ねるのではなく、フィードバックループ内で結果を検証し、プロンプトを見直し、変更を検証するからです。本稿は AI を記述するために使用される擬人化された言語を批判しており、「陰謀」などの用語は技術的な問題が存在する場所に人間の動意を不当に暗示することを示唆しているとしています。 今後の議論では、AI を別個の存在として描く枠組みから転じ、解釈への問いかけや誤りへの認識においてユーザーの専門性を育むことに焦点を移すべきです。開発者および企業に対しては、恐怖を煽る比喩ではなく正確な工学用語を採用することで、より良いリスク管理と説明責任を実現できます。真の熟達とは、どのような質問が重要かを理解し、熟練した運用と盲目的な委任を見極めることであり、不完全なパフォーマンスがツールの有用性や作業者の責任を否定するものではありません。

2026/10/13 1:13

C で構築されたモダンな Web アプリ

## Japanese Translation: 本テキストは、2026 年に C と CGI を OpenBSD 上で構築された独自の商用 Web アプリケーション「marketyour.games」について説明しています。このプロジェクトは現代のフレームワークよりも極度な簡潔性とセキュリティを優先しており、「BCHS」スタック(OpenBSD、C、httpd、SQLite)を採用し、外部のフレームワークや独立したデータベースサーバーは一切使用しません。核心的な革新点は、アプリケーション全体が静的にリンクされた単一のバイナリとして動作し、ランタイム依存関係がゼロであるというアーキテクチャにあります。デプロイはファイルを 1 つだけフォルダに配置するだけであり、古いバージョンを置き換えるだけで済みます。再起動やダウンタイムも不要です。 セキュリティは OpenBSD のデフォルト設定を通じて強制されており、httpd に対して `chroot` を適用し、C プログラムに対して `pledge` および `unveil` などのツールを使用して制約を課します。アーキテクチャは、すべての HTTP リクエストごとに新しいプロセスをフォークし、コードから直接アセットを提供することでメモリ内に完全に収まり、すべてのトラフィックを httpd を介して CGI バイナリにルーティングするという方式に基づいています。このアプローチでは JavaScript テンプレート言語を使用しない(プログレッシブ改善に従う)とともに、安定した CGI 1.1 規格に準拠しますが、使いやすさを犠牲にして制御性を追求します。 主な利点としては、サプライチェーンリスクが著しく低減すること—依存するのは C コンパイラーと 3 つのライブラリ(`libcurl`、`libsodium`、組み込み済みの `libcjson`)のみ—、そして GDB のような標準ツールによるデバッグが容易であることです。アプリケーションは通常の実行ファイルだからです。しかしながら、この手法では開発者がデータを解析するためのロジック(クッキー、クエリ、フォーム)やカスタムヘッダーの管理を自ら実装する必要があり、複雑な依存関係グラフではなく、基本的な HTTP 概念と Vim のような古典的なツール(プラグインなし)を活用する姿勢を選択します。

2026/10/13 4:40

ZX Spectrum 向けのデモシーンイントロを作成する

## Japanese Translation: 著者は、標準的な 128KB の ZX Spectrum にて手書きのレトロなイントロを成功裏に作成し、高度に最適化されたアセンブリ言語プログラミングにより複雑なビジュアルとオーディオを実現した。2 ヵ月間(2025 年 12 月から開始)にわたり、約 19KB のコード(具体的には 10287 バイトのメインルーチン)を書き下し、内蔵 ROM を書き換えることでカスタムフォント「Cartoon」を用いたスムーズなスクロールテキストを作成し、また Amiga モジュール「Milkman」を変換して 3 チャネル AY サウンドトラックを生成した。限られたメモリ制限を管理するため、アセットは BASIC ロードに分割され、ルーチンはオーバーヘッドを避けるために特定のアドレスでハードコーディングされた。技術的な最適化としては、Z80 RL 命令を用いてスクロールテキストの回転を実現し、スキャンライン衝突を避けるために Ruby で生成した座標テーブルを事前計算してスターフィールド効果を再現し、さらにサウンドチップから直接振幅レジスタを読み取ってバウンス VU メーターを実装している。プロジェクトは 1980 年代後半の Amiga クrack イントロに触発され、本物の Spectrum +3上でローカル TNFS サポートのある Makefile 駆動のビルドシステムを用いて開発された。最終的な.tap ファイルは Web ブラウザまたは pouet.net を経由して入手でき、レトロなハードウェア上で高忠実度な体験を提供し、極限を効率的に達成したコーディングの実証として立っている。