>サイトトップへ >このカテゴリの一覧へ

X 3010

:2003 (ISO/IEC 9899:1999)

(1) 

まえがき

この規格は,工業標準化法第 14 条によって準用する第 12 条第 1 項の規定に基づき,社団法人情報処理

学会情報規格調査会(IPSJ)/財団法人日本規格協会(JSA)から,工業標準原案を具して日本工業規格を改正

すべきとの申出があり,日本工業標準調査会の審議を経て,

経済産業大臣が改正した日本工業規格である。

これによって,JIS X 3010:1996 は改正され,この規格に置き換えられる。

改正に当たっては,日本工業規格と国際規格との対比,国際規格に一致した日本工業規格の作成及び日

本工業規格を基礎にした国際規格原案の提案を容易にするために,ISO/IEC 9899:1999,Programming

languages

―C 及び ISO/IEC 9899 Technical Corrigendum 1:2001 を基礎として用いた。

JIS X 3010

には,次に示す附属書がある。

附属書 A(参考)言語の構文の要約

附属書 B(参考)ライブラリの要約

附属書 C(参考)副作用完了点

附属書 D(規定)国際文字名

附属書 E(参考)処理系限界

附属書 F(規定)IEC 60559 浮動小数点算術

附属書 G(参考)IEC 60559 に適合する複素数計算

附属書 H(参考)言語共通算術

附属書 I(参考)共通の警告

附属書 J(参考)可搬性

附属書 1(参考)ISO/IEC 9899:1999(Programming languages―C)及び

ISO/IEC 9899 Technical Corrigendum 1:2001


X 3010

:2003 (ISO/IEC 9899:1999)

(2) 

目  次

ページ

序文

1

1.

  適用範囲

1

2.

  引用規格

2

3.

  用語及び記号の定義

2

3.1

  アクセス(access

2

3.2

  境界調整(alignment

2

3.3

  実引数[argumentactual argumentactual parameter(廃止予定)]

3

3.4

  動作(behavior

3

3.5

  ビット(bit

3

3.6

  バイト(byte

3

3.7

  文字(character

3

3.8

  制約(constraint

4

3.9

  正しい丸めの結果(correctly rounded result

4

3.10

  診断メッセージ(diagnostic message

4

3.11

  前方参照(forward reference

4

3.12

  処理系(implementation

4

3.13

  処理系限界(implementation limit

4

3.14

  オブジェクト(object

4

3.15

  仮引数[parameterformal parameterformal argument(廃止予定)]

4

3.16

  推奨実装仕様(recommended practice

4

3.17

  値(value

4

3.18

éxù

5

3.19

ëxû

5

4.

  規格合致性

5

5.

  環境

6

5.1

  概念モデル

6

5.2

  環境考慮事項

12

6.

  言語

21

6.1

  記法

21

6.2

  概念

21

6.3

  型変換

31

6.4

  字句要素

35

6.5

  式

48

6.6

  定数式

70

6.7

  宣言

71


X 3010

:2003 (ISO/IEC 9899:1999)  目次

(3) 

ページ

6.8

  文及びブロック

100

6.9

  外部定義

107

6.10

  前処理指令

111

6.11

  今後の言語の方針

124

7.

  ライブラリ

124

7.1

  概説

124

7.2

  診断機能<assert.h> 

128

7.3

  複素数計算<complex.h>

129

7.4

  文字操作<ctype.h> 

136

7.5

  エラー<errno.h> 

138

7.6

  浮動小数点環境<fenv.h> 

139

7.7

  浮動小数点型の特性<float.h>

146

7.8

  整数型の書式変換<inttypes.h> 

146

7.9

  代替つづり<iso646.h> 

149

7.10

  整数型の大きさ<limits.h> 

149

7.11

  文化圏固有操作<locale.h> 

149

7.12

  数学<math.h>

155

7.13

  非局所分岐<setjmp.h> 

175

7.14

  シグナル操作<signal.h> 

177

7.15

  可変個数の実引数<stdarg.h> 

179

7.16

  論理型及び論理値<stdbool.h>

182

7.17

  共通の定義<stddef.h> 

183

7.18

  整数型<stdint.h> 

183

7.19

  入出力<stdio.h> 

188

7.20

  一般ユーティリティ<stdlib.h> 

220

7.21

  文字列操作<string.h> 

232

7.22

  型総称数学関数<tgmath.h> 

238

7.23

  日付及び時間<time.h>

241

7.24

  多バイト文字及びワイド文字拡張ユーティリティ<wchar.h> 

247

7.25

  ワイド文字種分類及びワイド文字大文字小文字変換ユーティリティ<wctype.h>

278

7.26

  今後のライブラリの方針

283

附属書 A(参考)  言語の構文の要約

285

附属書 B(参考)  ライブラリの要約

285

附属書 C(参考)  副作用完了点

285

附属書 D(規定)  国際文字名

285

附属書 E(参考)  処理系限界

285

附属書 F(規定)  IEC 60559 浮動小数点算術

285

附属書 G(参考)  IEC 60559 に適合する複素数計算

285

附属書 H(参考)  言語共通算術

285


X 3010

:2003 (ISO/IEC 9899:1999)  目次

(4) 

ページ

附属書 I(参考)  共通の警告

285

附属書 J(参考)  可搬性

285

附属書 1(参考)  ISO/IEC 9899:1999Programming languagesC)及び ISO/IEC 9899 Technical 

Corrigendum 1:2001 

286

参考文献

287

索引

289

 


     

日本工業規格

JIS

 X

3010

:2003

(ISO/IEC 9899

:1999

)

プログラム言語 C

Programming languages

−C

序文  この規格は,1999 年に第 2 版として発行された ISO/IEC 9899:1999,(Programming languages―C)

及び Technical Corrigendum 1 (2001)について,技術的内容を変更することなく日本工業規格として採用する

ために作成されたものであり,ISO/IEC 9899:1999 の本体については,原国際規格の同項目を全文翻訳し,

ISO/IEC 9899:1999

の附属書については,それぞれ原国際規格の同項目の内容を引用するものとした。た

だし,技術に関する正誤表(Technical Corrigendum)については,編集し,一体とした。

なお,この規格での点線の下線を施してある“参考”は,原国際規格にない事項である。

新しい装置及び拡張文字集合を導入するために,新しい機能をこの規格に追加する可能性がある。言語

の箇条及びライブラリの箇条では,処理系作成者及びプログラマに対し,正しい使用法だが将来の追加機

能と相いれない可能性がある使用法について警告している。

廃止予定の機能がある。これはこの規格の将来の改正で,削除されるかもしれないことを意味する。こ

れらは広く普及している使用法であるため残されている。しかし,今後の処理系又はプログラムではこれ

らの使用は推奨できない[

“今後の言語の方針”

6.11)又は“今後のライブラリの方針”

7.26)参照]

この規格は,大きく次の四つに分かれる。

―  諸前提事項(1.4.

―  C プログラムの翻訳環境及び実行環境(5.

―  言語の構文規則,制限及び意味規則(6.

―  ライブラリの機能(7.

例は,記述された構文の有効な形式を例証するためにある。脚注は,その箇条又は他で述べられている

規則から導かれることを強調するためにある。参照は,他の関連する箇条を参照するためにある。推奨す

る実装は,処理系作成者に対して勧告又は指針を与えるためにある。附属書は,付加情報を提供し,この

規格に含まれる情報を要約する。参考文献は,この規格を作成する過程で参照した文献を示す。

言語の箇条(6.)は,

“The C Reference Manual”に基づいている。

ライブラリの箇条(7.)は,1984 /usr/group Standard に基づいている。

1.

適用範囲  この規格は,C プログラム言語で書いたプログラムの形式を規定し,そのプログラムの解

釈を規定する(

1

)

。この規格は,次の事項を規定する。

−  C プログラムの表現方法

−  C 言語の構文規則と制約

───────────────────────────────────────────────

(1)

この規格は,多様なデータ処理システム間での C プログラムの可搬性を促進するために制定された。

この規格は,処理系の作成者及びプログラマによる使用を想定している。


2

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  C プログラムを解釈するための意味規則

−  C プログラムが処理する入力データの表現方法

−  C プログラムが生成する出力データの表現方法

−  C 言語の規格合致処理系が C プログラムに課す制約及び限界

この規格は,次の事項を規定しない。

−  データ処理システムで使用するために,C プログラムを変換する機構

−  データ処理システムで使用するために,C プログラムを呼び出す機構

−  C プログラムで使用するために,入力データを変換する機構

−  C プログラムが出力データを生成した後に,そのデータを変換する機構

−  特定のデータ処理システム又は特定の処理系において,許容範囲を超えるプログラムの大きさ又は複

雑さ及びそのデータの大きさ又は複雑さ

−  規格合致処理系を支援するためにデータ処理システムが備えるべき最小限の要求条件

備考  この規格の対応国際規格を,次に示す。

なお,対応の程度を表す記号は,ISO/IEC Guide 21 に基づき,IDT(一致している)

,MOD

(修正している)

,NEQ(同等でない)とする。

ISO/IEC 9899:1999

,Programming languages―C (IDT)

2.

引用規格  次に掲げる規格は,この規格に引用されることによって,この規格の規定の一部を構成す

る。これらの引用規格のうちで,発効年又は発行年を付記してあるものは,記載の年の版だけがこの規格

の規定を構成するものであって,その後の改正版・追補は適用しない。発効年又は発行年を付記していな

い引用規格は,その最新版(追補を含む。

)を適用する。

JIS X 0001

:1994  情報処理用語―基本用語

備考  ISO/IEC 2382-1:1993,Information technology―Vocabulary―Part 1: Fundamental terms が,この

規格と一致している。

JIS X 0201

  7 ビット及び 8 ビットの情報交換用符号化文字集合

備考  ISO/IEC 646,Information technology―ISO 7-bit coded character set for information interchange か

らの引用事項は,この規格の該当事項と同等である。

JIS X 0301

  日付及び時刻の表記

備考  ISO 8601,Data elements and interchange formats―Information interchange―Representation of

dates and times

が,この規格と一致している。

ISO 31-11:1992

,Quantities and units―Part 11:Mathematical signs and symbols for use in the physical sciences

and technology

ISO 4217

,Codes for the representation of currencies and funds

ISO/IEC 10646 (all parts)

,Information technology―Universal Multiple-Octet Coded Character Set (UCS)

参考  ISO/IEC 10646-1:1993 は,JIS X 0221:1995  国際符号化文字集合(UCS)―第 1 部:体系及

び基本多言語面と一致している。

IEC 60559:1989

,Binary floating-point arithmetic for microprocessor systems(この規格の番号は,以前 IEC 

559:1989

であった。


3

X 3010

:2003 (ISO/IEC 9899:1999)

     

3.

用語及び記号の定義  この規格で用いる主な用語の定義は,次による。その他の用語は,その用語を

太字で示した場所,又は構文規則の左側に出現した場所で定義したとみなす。この規格で明示的に定義す

る用語は,この規格以外で定義される類似の用語を暗黙に参照すると考えてはならない。この規格で定義

しない用語は,JIS X 0001 に従って解釈する。この規格で定義しない数学記号は,ISO 31-11 に従って解釈

する。

3.1

アクセス(access)  <実行時の動作>オブジェクトの値を読み取る,又は変更すること。

参考1.  これらの二つの動作のうちのいずれか一方だけを意味する場合は,“読み取る”又は“変更す

る”という用語を使う。

2.

“変更する”は,格納する新しい値が,格納前の値と同じである場合も含む。

3.

評価されない式は,オブジェクトをアクセスしない。

3.2

境界調整(alignment)  特定の型のオブジェクトを特定のバイトアドレスの倍数のアドレスをもつ

記憶域境界に割り付ける要求。

3.3

実引数[argumentactual argumentactual parameter(廃止予定)]  関数呼出し式において,括

弧で囲まれコンマで区切られた並びの中の式,又は関数形式マクロの呼出しにおいて,括弧で囲まれコン

マで区切られた並びの中の前処理字句の列。

3.4

動作(behavior)  外から見る様子又は動作。

3.4.1

処理系定義の動作(implementation-defined behavior)  未規定の動作のうち,各処理系が選択し

た動作を文書化するもの。

例  処理系定義の動作の例としては,符号付き整数を右シフトした場合の最上位ビットの伝ぱ(播)

法がある。

3.4.2

文化圏固有動作(locale-specific behavior)  国家,文化及び言語の地域規約に依存する動作であり,

各処理系がその動作を文書化するもの。

例  文化圏固有動作の例としては,islower 関数が 26 種類のラテン小文字以外の文字に対し,真を

返すかどうかがある。

3.4.3

未定義の動作(undefined behavior)  可搬性がない若しくは正しくないプログラム構成要素を使

用したときの動作,又は正しくないデータを使用したときの動作であり,この規格が何ら要求を課さない

もの。

参考  未定義の動作に対して,その状況を無視して予測不可能な結果を返してもよい。翻訳時又はプ

ログラム実行時に,文書化された,環境に特有な方法で処理してもよい(診断メッセージの発

行を伴っても伴わなくてもよい。

。さらに(診断メッセージを出力し)翻訳又は実行を中断し

てもよい。

例  未定義の動作の例としては,整数演算のオーバフローに対する動作がある。

3.4.4

未規定の動作(unspecified behavior)  この規格が,二つ以上の可能性を提供し,個々の場合にど

の可能性を選択するかに関して何ら要求を課さない動作。

例  未規定の動作の例としては,関数の実引数の評価順序がある。

3.5

ビット(bit)  2 種類の値のうちの一方を値としてもつオブジェクトを保持するために十分な大き

さをもつ実行環境でのデータ記憶域の単位。

参考1.  オブジェクトの個々のビットのアドレスを表現できる必要はない。

2.

ビットがもちうる 2 種類の値のうちの一方を値 0 という。ビットの値を値 0 以外にすること

を,この規格では,

“ビットをセットする”という。


4

X 3010

:2003 (ISO/IEC 9899:1999)

     

3.6

バイト(byte)  実行環境の基本文字集合の任意の要素を保持するために十分な大きさをもつアド

レス付け可能なデータ記憶域の単位。

参考1.  オブジェクトの個々のバイトのアドレスは,一意に表現できる。

2.

バイトは連続するビットの列から成る。1 バイト中のビットの個数は,処理系定義である。

最も重みの小さいビットを

最下位ビット(low-order bit)と呼び,最も重みの大きいビットを

最上位ビット(high-order bit)と呼ぶ。

3.7

文字(character)  <抽象的意味>データを構成する,制御する,又は表現するために使用する基

本要素から成る集合の要素。

3.7.1

文字(character),バイト文字(single-byte character)  <プログラム言語 C での意味>1 バイ

トに納まるビット表現。

3.7.2

多バイト文字(multibyte character)  ソース環境又は実行環境の拡張文字集合の要素を表す 1 バ

イト以上のバイトの列。

参考  拡張文字集合は,基本文字集合を包含する。

3.7.3

ワイド文字(wide character)  型 wchar_t のオブジェクトに納まり,その時点のロケールでの任

意の文字を表現できるビット表現。

3.8

制約(constraint)  言語要素に関する規定を解釈するに当たっての構文上又は意味上の制限。

3.9

正しい丸めの結果(correctly rounded result)  有効な丸めモードの下で得られる結果の形式の表現

で,無制限の範囲及び精度を仮定して得られる結果に最も近いもの。

3.10

診断メッセージ(diagnostic message)  処理系が出力するメッセージのうち,処理系定義の部分集

合に属するメッセージ。

3.11

前方参照(forward reference)  その箇条に関連する付加情報を含むこの規格の前方の箇条への参照。

3.12

処理系(implementation)  特定の翻訳環境中において特定の制御オプションの下で走行し,特定の

実行環境用にプログラムを翻訳し,その実行環境における関数の実行をサポートする特定のソフトウェア

集合。

3.13

処理系限界(implementation limit)  処理系がプログラムに課す制限。

3.14

オブジェクト(object)  その内容によって,値を表現することができる実行環境中の記憶域の部分。

参考  オブジェクトを参照する場合,オブジェクトは,特定の型をもっていると解釈してもよい

6.3.2.1 参照)

3.15

仮引数[parameterformal parameterformal argument(廃止予定)]  関数宣言若しくは関数定

義の一部として宣言され,関数に入る時点で値を得るオブジェクト,又は関数形式マクロ定義におけるマ

クロ名の直後の括弧で囲まれコンマで区切られた並びに現れる識別子。

3.16

推奨実装仕様(recommended practice)  この規格の趣旨に沿うために強く推奨する規定。しかし,

処理系によっては非現実的な場合もある。

3.17

値(value)  オブジェクトが特定の型をもっていると解釈する場合のオブジェクトの内容の厳密な

意味。

3.17.1

処理系定義の値(implementation-defined value)  未規定の値のうち,各処理系が選択した値を文

書化するもの。

3.17.2

不定の値(indeterminate value)  未規定の値又はトラップ表現。

3.17.3

未規定の値(unspecified value)  適切な型の正しい値であり,この規格が,個々の場合にどの値

を選択するかに対して何ら要求を課さないもの。


5

X 3010

:2003 (ISO/IEC 9899:1999)

     

参考  未規定の値は,トラップ表現となることはない。

3.18

éxù  の切上げ,すなわち,以上の最小の整数。

é2.4ù  は,3。é−2.4ù  は,−2。

3.19

ëxû  の切下げ,すなわち,以下の最大の整数。

ë2.4û  は,2。ë−2.4û  は,−3。

4.

規格合致性  この規格では,“…(し)なければならない”という表現は,処理系又はプログラムに対

する要求を表す。さらに,

“…(し)てはならない”という表現は,禁止を表す。

この規格の制約以外の箇所で現れる“…(し)なければならない”又は“…(し)てはならない”とい

う要求をプログラムが守っていない場合,その動作は未定義とする。この規格では,このほかに,用語“未

定義の動作”を使うことによるか又は動作の明示的な定義を与えないことによって未定義の動作を示すこ

ともある。これらの三つの書き方は強調度において何ら変わりはなく,それらはすべて“未定義の動作”

を規定する。

プログラムが未規定の動作を含んでいても,それ以外のあらゆる側面において正しく,かつ正しいデー

タを操作する場合,それは,正しいプログラムとみなし,5.1.2.3 に従って動作しなければならない。

#error

前処理指令が条件付き取込みによって読み飛ばされるグループの中にない限り,処理系は,

#error

前処理指令を含む前処理翻訳単位の翻訳を成功させてはならない。

規格厳密合致プログラム(strictly conforming program)は,この規格で規定する言語機能及びライブラリ

だけを使用しなければならない(

2

)

。さらに,いかなる未規定の動作,未定義の動作又は処理系定義の動作

に依存する出力も生成してはならず,しかもどのような最低限の処理系限界も超えてはならない。

規格合致処理系(conforming implementation)は,ホスト及びフリースタンディングの 2 種類とする。規

格合致ホスト処理系(conforming hosted implementation)は,任意の規格厳密合致プログラムを受理しなけ

ればならない。

規格合致フリースタンディング処理系(conforming freestanding implementation)は,次の二

つの条件を満たす任意の規格厳密合致プログラムを受理しなければならない。

−  複素数型を使っていない。

−  ライブラリの箇条(7.)で規定する機能の使用を,標準ヘッダ<float.h>,<iso646.h>,<limits.h>,

<stdarg.h>

,<stdbool.h>,<stddef.h>及び<stdint.h>の内容に限定している。

規格合致処理系は,

任意の規格厳密合致プログラムの動作を変更しない限り,

(ライブラリ関数の追加を含

───────────────────────────────────────────────

(2)

規格厳密合致プログラムは,どの処理系でもサポートしているわけではない機能(

附属書 の中に例

がある。)を使うことができる。ただし,その機能を使うことができるのは,それが適切なマクロを

もつ#ifdef 指令とそれに対応する#endif 指令とに囲まれている場合に限る。次に示すプログラム

片がその例である。

        #ifdef _ _STDC_IEC_559_ _ /* FE_UPWARD

が定義されている */

           /* ... */

       fesetround(FE_UPWARD);

       /*

... */

    #endif


6

X 3010

:2003 (ISO/IEC 9899:1999)

     

む)拡張をしてもよい(

3

)

規格合致プログラム(conforming program)は,ある規格合致処理系が受理することができるプログラム

とする(

4

)

処理系は,すべての処理系定義の特性,すべての文化圏固有の特性及びすべての拡張を定義した文書を

伴わなければならない。

前方参照  エラー指令(6.10.5),可変個数実引数<stdarg.h>(7.15),共通の定義<stddef.h>(7.17),

条件付き取込み(6.10.1

,整数型<stdint.h>(7.18

,整数型の大きさ<limits.h>(7.10

,代替つづり

<iso646.h>

7.9

,浮動小数点型の特性<float.h>(7.7

,論理型及び値<stdbool.h>(7.16

5.

環境  処理系は,二つのデータ処理システム環境の中で C ソースファイルを翻訳し,C プログラムを

実行する。この規格では,これらの環境をそれぞれ

翻訳環境(translation environment)及び実行環境(execution

environment

)と呼ぶ。これらの環境がもつ特性は,構文規則及び意味規則に従って構成された規格合致 C

プログラムのその規格合致処理系における実行結果を定義し,制約する。

前方参照  この箇条(5.)では,実際の前方参照の一部だけを示す。

5.1

概念モデル

5.1.1

翻訳環境

5.1.1.1

プログラム構成  一つの C プログラムの全体を同時に翻訳する必要はない。プログラムのテキス

トは,この規格で

ソースファイル(source file)[又は前処理ファイル(preprocessing file)]と呼ぶ単位で保

持する。一つのソースファイルに,#include 前処理指令を通して取り込むすべてのヘッダ及びソースフ

ァイルを加えたものを

前処理翻訳単位(preprocessing translation unit)と呼ぶ。前処理完了後の前処理翻訳

単位を

翻訳単位(translation unit)と呼ぶ。過去に翻訳した翻訳単位を,個々に又はライブラリ中にまとめ

て保存してもよい。一つのプログラムを構成する各翻訳単位は,

(例えば)識別子が外部結合をもつ関数の

呼出し,識別子が外部結合をもつオブジェクトの操作,又はデータファイルの操作によって,互いに連絡

する。複数の翻訳単位を別々に翻訳し,後で結合して一つの実行可能プログラムを作成してもよい。

前方参照  外部定義(6.9),識別子の結合(6.2.2),前処理指令(6.10

5.1.1.2

翻訳フェーズ  次に示すフェーズによって,翻訳上の構文規則間の優先順位を規定する(

5

)

(1) 必要ならば,物理的なソースファイルの多バイト文字を,対応するソース文字集合に,処理系定義

の方法で,写像する(この際,行の終わりを示すものに対して改行文字を導入する。

。3 文字表記

を,対応する単一の文字の内部表現に置き換える。

(2) 逆斜線文字(\)の直後に改行文字が現れた場合,それらの 2 文字を削除する。これによって物理ソ

ース行を接合して論理ソース行を作成する。一つの物理ソース行においてこの接合の対象となるの

は,その行の最後の逆斜線文字だけとする。空でないソースファイルは,改行文字で終了しなけれ

───────────────────────────────────────────────

(3)

これは,規格合致処理系がこの規格で明示的に予約する識別子以外の識別子を予約してはならないこ

とを意味する。

(4)

規格厳密合致プログラムは,規格合致処理系間で,最大限の可搬性を意図したプログラムである。規

格合致プログラムは,規格合致処理系における可搬性のない機能に依存してもよい。

(5)

処理系は,実際には,ここに示す幾つかのフェーズを一つにまとめてもよいが,ここに示す別々のフ

ェーズが存在するとみなした場合と同じ規則に従って動作しなければならない。


7

X 3010

:2003 (ISO/IEC 9899:1999)

     

ばならない。さらに,この改行文字の直前に(接合を行う前の時点で)逆斜線文字があってはなら

ない。

(3) ソースファイルを,前処理字句(

6

)

及び空白類文字(注釈を含む。

)の並びに分割する。ソースファイ

ルは,前処理字句の途中又は注釈の途中で終了してはならない。各注釈を,一つの空白文字に置き

換える。改行文字を保持する。改行文字を除く空白類文字の並びを保持するか一つの空白文字に置

き換えるかは,処理系定義とする。

(4) 前処理指令を実行し,マクロ呼出しを展開する。さらに,_Pragma 単項演算子式を実行する。字句

連結(6.10.3.3 参照)の結果として生成される文字の並びが国際文字名の構文規則に一致する場合,

その動作は未定義とする。#include 前処理指令に指定された名前をもつヘッダ又はソースファイ

ルに対して,フェーズ(1)からフェーズ(4)までの処理を再帰的に行い,すべての前処理指令を

削除する。

(5) 文字定数及び文字列リテラル中のソース文字集合の各要素及び各逆斜線表記を,それぞれに対応す

る実行文字集合の要素に変換する。対応する要素が存在しない場合,ナル(ワイド)文字以外の処

理系定義の要素に変換する(

7

)

(6) 隣接する文字列リテラル字句同士を連結する。

(7) 字句を分離している空白類文字は,もはや意味をもたない。各前処理字句を字句に変換する。その

結果,生成された字句の列を構文的及び意味的に解析し,翻訳単位として翻訳する。

(8) すべての外部オブジェクト参照及び外部関数参照を解決する。その翻訳単位中に定義されていない

関数及びオブジェクトへの外部参照を解決するため,ライブラリの構成要素を連係する。これらす

べての翻訳出力をまとめて,実行環境上での実行に必要な情報を含む一つのプログラムイメージを

作る。

前方参照  3 文字表記(5.2.1.1

,外部定義(6.9

,国際文字名(6.4.3

,字句要素(6.4

,前処理指令(6.10

5.1.1.3

診断メッセージ  前処理翻訳単位又は翻訳単位が何らかの構文規則違反又は制約違反を含む場

合(たとえ,その動作が未定義の動作又は処理系定義の動作として明示的に規定されていても)

,規格合致

処理系は,その前処理翻訳単位又は翻訳単位に対して,少なくとも一つの(処理系定義の方法で識別され

る)診断メッセージを出力しなければならない。その他の状況においては,診断メッセージを出力しなく

てもよい(

8

)

例  処理系は,次に示す翻訳単位に対して診断メッセージを出力しなければならない。

  char

i;

  int

i;

その理由は,この規格での記述が,ある構文要素に対する動作を,制約違反かつ結果として未定

───────────────────────────────────────────────

(6)

ソースファイルの文字を前処理字句に分ける処理は,文脈に依存する(6.4 で規定する。

。例えば,

#include

前処理指令の中では<の扱いが他の場合と異なる。

(7)

処理系は,対応する要素がないソース文字集合の要素のすべてを,実行文字集合の同じ要素に変換す

る必要はない。

(8)

処理系は,各違反の性質及び可能な限り,違反箇所を明らかにしたほうがよいことを意図している。

もちろん,正しいプログラムを正しく翻訳している限り,処理系が任意の個数の診断メッセージを出

力することは自由である。処理系は正しくないプログラムを最後まで翻訳し続けてもよい。


8

X 3010

:2003 (ISO/IEC 9899:1999)

     

義の動作になると規定している場合は,制約違反に対する診断メッセージを出力しなければなら

ないからである。

5.1.2

実行環境  フリースタンディング(freestanding)実行環境及びホスト(hosted)実行環境の 2 種類

の実行環境を定義する。いずれの場合も,実行環境が指定された C の関数を呼び出すときの処理を,

プロ

グラム開始処理(program startup)という。静的記憶域期間をもつすべてのオブジェクトをプログラム開始

処理以前に

初期化(initialize)(それらの初期値に設定)しなければならない。初期化の方法及び時期につ

いて,これ以外は,未規定とする。

プログラム終了処理(program termination)は,実行環境に制御を戻す。

前方参照  オブジェクトの記憶域期間(6.2.4),初期化(6.7.8

5.1.2.1

フリースタンディング環境  フリースタンディング環境では,オペレーティングシステムのいか

なる支援もなしに C プログラムの実行を行う。プログラム開始時に呼び出される関数の名前及び型は,処

理系定義とする。フリースタンディング環境でプログラムが利用できるライブラリ機能は,4.で要求する

最低限必要なライブラリ機能を除いて,処理系定義とする。

フリースタンディング環境におけるプログラム終了処理の効果は,処理系定義とする。

5.1.2.2

ホスト環境  ホスト環境を提供する必要はないが,提供する場合,5.1.2.2.15.1.2.2.3 の規定に合

致しなければならない。

5.1.2.2.1

プログラム開始処理  プログラム開始処理において呼び出される関数の名前は,main とする。

処理系は,この関数に対して関数原型を宣言しない。この関数は,次の 4 種類の方法のいずれかで定義し

なければならない。

−  返却値の型 int をもち仮引数をもたない関数

int main(void) { /*

... */ }

−  二つの仮引数をもつ関数(仮引数は,これらが宣言された関数に対して局所的であるため,どのよう

な名前を使用してもよいが,ここでは argc 及び argv とする。

int main(int argc, char * argv[]) { /*

... */ }

−  上に掲げた二つの方法のいずれかと等価な方法(

9

)

−  上に掲げた三つの方法のいずれでもない処理系定義の方法

二つの仮引数を定義する場合,関数 main の仮引数は,次の制約に従わなければならない。

−  argc の値は,非負でなければならない。

−  argv[argc]は,空ポインタでなければならない。

−  argc の値が正の場合,argv[0]から argv[argc-1]までの配列要素は,文字列へのポインタでなけ

ればならない。これらの文字列には,プログラム開始処理に先立ち,ホスト環境が処理系定義の値を

与える。これは,ホスト環境中のどこかでプログラム開始処理に先立って決定された情報をプログラ

ムに与えることを目的とする。ホスト環境が大文字と小文字のいずれか一方しか扱えない場合,処理

系が main に渡す文字列は,小文字にしなければならない。

−  argc の値が正の場合,argv[0]が指す文字列は,

プログラム名(program name)を表す。ホスト環

境からプログラム名を得ることができない場合,argv[0][0]は,ナル文字でなければならない。argc

の値が 1 より大きい場合,argv[1]から argv[argc-1]までが指す文字列は,

プログラム仮引数

───────────────────────────────────────────────

(9)

したがって,int は,int として定義された型定義名で置き換えることができるし,argv の型は,

char ** argv

と書くこともできる。


9

X 3010

:2003 (ISO/IEC 9899:1999)

     

(program parameter)を表す。

−  仮引数 argc,argv 及び argv 配列が指す文字列は,プログラムによって変更可能でなければならな

い。さらに,プログラム開始処理からプログラム終了処理までの間,最後に格納された値を保持しな

ければならない。

5.1.2.2.2

プログラムの実行  ホスト環境では,プログラムは,ライブラリの箇条(7.)で規定するすべ

ての関数,マクロ,型定義及びオブジェクトを使用してよい。

5.1.2.2.3

プログラム終了処理  main 関数の返却値の型が int と適合する場合,main 関数の最初の呼出

しからの復帰は,main 関数が返す値を実引数としてもつ exit 関数の呼出しと等価とする(

10

)

。main 関

数を終了する}に到達した場合,main 関数は,値 0 を返す。main 関数の返却値の型が int と適合しない

場合,ホスト環境に戻される終了状態は,未規定とする。

前方参照  exit 関数(7.20.4.3),用語の定義(7.1.1

5.1.2.3

プログラムの実行  この規格における意味規則の規定では,最適化の問題を無視して抽象計算機

の動作として記述する。

ボラタイルオブジェクトへのアクセス,オブジェクトの変更,ファイルの変更,又はこれらのいずれか

の操作を行う関数の呼出しは,すべて

副作用(side effect)と呼び(

11

)

,実行環境の状態に変化を生じる。式

の評価は,副作用を引き起こしてもよい。

副作用完了点(sequence point)と呼ばれる実行順序における特

定の点において,それ以前の評価に伴う副作用は,すべて完了していなければならず,それ以降の評価に

伴う副作用が既に発生していてはならない。

(副作用完了点の要約を

附属書 に示す。)

抽象計算機では,すべての式は意味規則で規定するとおりに評価する。実際の処理系では,値が使用さ

れないこと,及び(関数の呼出し又はボラタイルオブジェクトのアクセスによって起こる副作用を含め)

副作用が必要とされないことが保証できる式は,評価しなくてよい。

シグナルの受理によって抽象計算機が処理を中断する場合,その直前の副作用完了点でのオブジェクト

の値だけが信頼できる。直前の副作用完了点と次の副作用完了点との間で変更される可能性があるオブジ

ェクトは,正しい値を受け取り終わっているとは限らない。

規格合致処理系は,少なくとも次の要求を満たさなければならない。

−  副作用完了点において,ボラタイルオブジェクトは,それまでのアクセスがすべて完了していること

及び後続のアクセスが行われていないこと,という意味において安定している。

−  プログラム終了の時点で,ファイルに書き込まれたすべてのデータは,プログラムの抽象意味規則に

従った実行が生成する結果と一致する。

───────────────────────────────────────────────

(10)

6.2.4

に従い,main 関数の最初の呼出しから復帰する場合,main 関数で宣言された自動記憶域期

間をもつオブジェクトの生存期間は,終了するが,exit 関数の呼出しの場合,その生存期間は,

終了しないかもしれない。

(11) 2

進浮動小数点算術に対する IEC 60559 規格は,利用者がアクセス可能なある種の状態フラグ及び

制御モードを要求する。浮動小数点の演算は,暗黙に状態フラグをセットし,モードは,浮動小数

点の演算結果の値に影響する。こうした浮動小数点の状態をサポートする処理系は,状態の変化を

副作用として認識しなければならない(詳細は,

附属書 参照)。浮動小数点環境ライブラリ

<fenv.h>

は,この副作用が問題となる場合は,それを処理系に示し,副作用が問題とならない場

合は,処理系を自由にしておくためのプログラム上の手段を提供する。


10

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  対話型装置に対する入出力動作は,7.19.3 で規定するとおりに行う。この要求は,入力要求メッセー

ジが実際にプログラムの入力待ち以前に現れることを確実にするため,バッファリングされない出力

又は行バッファリングされた出力ができる限り早く現れることを意図する。

どのようなものが対話型装置であるかは,処理系定義とする。

抽象意味規則と実際の意味規則とのより厳密な対応付けは,各処理系において定義してよい。

1.  処理系は,抽象意味規則と実際の意味規則とを 1 対 1 に対応させてもよい。このような処理系

では,任意の副作用完了点における実際のオブジェクトの値は,抽象意味規則で規定する値と

一致する。その場合,キーワード volatile は冗長となる。

別の実現例として,処理系は,それぞれの翻訳単位内で各種最適化処理を施してもよい。こ

の場合,翻訳単位の境界を越える関数呼出しが行われる場合だけは,実際の意味規則と抽象意

味規則とが一致することになる。このような処理系では,呼び出した関数と呼び出された関数

とが異なる翻訳単位に属する場合,各関数に入る時点及び関数からの戻りの時点において,す

べての外部結合オブジェクトの値及びそれらの中からポインタを介してアクセスできるすべて

のオブジェクトの値は,抽象意味規則での値と一致する。さらに,このような関数に入った時

点において,呼び出された関数のすべての仮引数の値及びそれらの中からポインタを介してア

クセスできるすべてのオブジェクトの値は,抽象意味規則での値と一致する。この形態の処理

系では,signal 関数によって起動される割込み処理ルーチンが参照するオブジェクトには,

明示的な volatile 記憶域の指定が必要であり,そのほかにも処理系定義の制約が必要であり

うる。

2.  次のプログラム片を実行する場合,

char c1, c2;

   /*

... */

c1 = c1 + c2;

“整数拡張”の規則に従って,抽象計算機はまずそれぞれの変数の値を int 型の大きさに拡張

し,次に二つの int の加算を行い,結果の切捨てを行う。実際の実行では,同一の結果を得る

ことだけが必要であり,オーバフローを起こさずに,二つの char の加算を実行できるのであ

れば,又はオーバフローが起こっても,例外にならずに,正しい結果を生成できるのであれば,

拡張を省くことができる。

3.  同様に,次のプログラム片では,

float f1, f2;

   double

d;

   /*

... */

f1 = f2 * d;

処理系が(例えば,d を型 double をもつ定数 2.0 に置き換えた場合のように)倍精度演算で

実行した場合と同じ結果になることを確認できるのならば,乗算を単精度演算で実行してもよ

い。

4.  ビット数が多いレジスタを採用している処理系は,意味規則を正しく守ることに留意しなけれ

ばならない。値は,それがレジスタに格納されて表現されるのか,又はメモリに格納されて表

現されるのか,ということとは独立である。例えば,データが暗黙にレジスタからメモリに退

避されることによってその値が変わることは,許されない。さらに,記憶域の種類ごとに決ま


11

X 3010

:2003 (ISO/IEC 9899:1999)

     

る精度にデータを丸めるためには,明示的にその記憶域へデータを格納し,再びそれを読み出

すことが必要である。特に,キャスト及び代入では,指定された変換を実際に実行する必要が

ある。次のプログラム片では,

double d1, d2;

   float

f;

d1 = f =

式;

d2 = (float)

式;

d1

及び d2 に代入される値は,いったん float に変換されたものでなければならない。

5.  浮動小数点型の式に対する再構成は,しばしば精度と範囲の制約によって制限される。処理系

は,たとえオーバフロー及びアンダフローが発生しない場合でも,丸め誤差のために,加算若

しくは乗算に対する数学的結合法則,又は数学的分配法則を一般に適用することはできない。

さらに,処理系は,一般的に,式の再構成の目的で 10 進定数を置き換えることはできない。次

のプログラム片では,実数に対する数学の諸規則の適用による式の再構成は,必ずしも正しい

とは限らない(

附属書 F.8 参照)。

double x, y, z;

   /*

... */

x = (x * y) * z;

// x *= y * z;

と等価ではない。

z = (x - y) + y ;

// z = x;

と等価ではない。

z = x + x * y;

// z = x * (1.0 + y);

と等価ではない。

y = x / 5.0;

// y = x * 0.2;

と等価ではない。

6.  式のグループ分けを次のプログラム例で示す。

int a, b;

   /*

... */

a = a + 32760 + b + 5;

この式文は,演算子の結合と優先順位に関する規則によって,

a = (((a + 32760) + b) + 5);

と同一の動作をする。したがって,加算(a + 32760)の結果が,b に加えられ,その結果が 5

に加えられ,その結果が a に代入される値となる。オーバフローが明示的なトラップを発生さ

せ,int で表現できる範囲が[

−32768,+32767]の計算機では,処理系は,この式を次のように書

き換えることはできない。

a = ((a + b) + 32765);

理由は,仮に a と b の値がそれぞれ

−32754 と−15 であった場合,加算 a + b は,トラップを

発生することになるが,元の式では発生しないからである。さらに,

a = ((a + 32765) + b);

又は

a = (a + (b + 32765));

にも書き換えられない。理由は,a と b の値がそれぞれ 4 と

−8 又は−17 と 12 かもしれないか

らである。しかし,オーバフローが何らかの値を生成させ,正のオーバフロー及び負のオーバ

フローが打ち消し合う計算機では,同じ結果が得られるので,処理系は上で述べた方法のいず

れにも書き換えることができる。


12

X 3010

:2003 (ISO/IEC 9899:1999)

     

7.  式のグループ分けは,その評価を完全に決定するものではない。次のプログラム片

#include <stdio.h>

   int

sum;

   char

*p;

   /*

... */

sum = sum * 10 - '0' + (*p++ = getchar());

では,式文は次のように書いた場合と同じにグループ分けされる。

sum = (((sum * 10) - '0') + ((*(p++)) = (getchar())));

しかし,p の実際の増加は,直前の副作用完了点と次の副作用完了点(セミコロンの位置)の

間の任意の時点で起きてよい。さらに,getchar の呼出しは,その返却値が必要となる以前の

任意の時点に起きてよい。

前方参照  signal 関数(7.14),型修飾子(6.7.3),式(6.5),ファイル(7.19.3),文(6.8

5.2

環境考慮事項

5.2.1

文字集合  ソースファイルでプログラムの記述に用いる文字集合[ソース文字集合(source character

set

,及び実行環境で解釈する文字集合[

実行文字集合(execution character set)]の二つの文字集合の定

義,並びにそれらの文字集合に関する文字の大小順序の定義がなければならない。ソース文字集合及び実

行文字集合のそれぞれは,更に,次の二つの集合に分けられる。

基本文字集合(basic character set)(その内容は,5.2.1 で規定する。)

−  (基本文字集合の要素ではない)0 個以上の文化圏固有の要素[

拡張文字(extended character)]の集

これら二つの集合の和を

拡張文字集合(extended character set)という。実行文字集合の要素の値は,処理

系定義とする。

文字定数又は文字列リテラルの中では,実行文字集合の要素をソース文字集合の対応する要素,又は逆

斜線(\)に続く一つ以上の文字から成る

逆斜線表記(escape sequence)によって表現しなければならない。

すべてのビットが 0 であるバイトを

ナル文字(null character)という。ナル文字は,実行基本文字集合中に

存在しなければならない。文字列の終わりを示すためにナル文字を用いる。

ソース基本文字集合及び実行基本文字集合は,少なくとも次に掲げる要素をもっていなければならない。

− 26 個のラテンアルファベットの

大文字(uppercase letter)

                                A B C D E F G H I J K L M

                N  O  P  Q  R  S  T  U  V  W  X  Y  Z

− 26 個のラテンアルファベットの

小文字(lowercase letter)

                                a b c d e f g h i j k l m

                n  o  p  q  r  s  t  u  v  w  x  y  z

− 10 個の 10 進

数字(digit)

                              0 1 2 3 4 5 6 7 8 9

− 29 個の図形文字

                               ! " # % & ' ( ) * + , - . / :

                ; < = > ? [

\ ] ^ _ { | } ~

−  空白文字

−  水平タブ,垂直タブ,及び書式送りのそれぞれを表す制御文字


13

X 3010

:2003 (ISO/IEC 9899:1999)

     

ソース基本文字集合の各要素の表現,及び実行基本文字集合の各要素の表現は,1 バイトの中に納まらな

ければならない。ソース基本文字集合及び実行基本文字集合の双方において,10 進数字に関する上の並び

において,0 の右側に並んでいる各文字の値は,一つ左側にある文字の値に比べ 1 だけ大きくなければな

らない。ソースファイルの中でテキストの各行の終わりを表す何らかの方法が存在しなければならない。

この規格では,行の終わりを示すものを一つの文字(改行文字)とみなして扱う。実行基本文字集合の中

には,警報,後退,復帰及び改行を表す制御文字がなければならない。

(識別子,文字定数,文字列リテラ

ル,ヘッダ名,注釈,又は字句に変換されることのない前処理字句の中を除いて,

)ソースファイル中にこ

れら以外の文字がある場合,動作は未定義とする。

参考  この規格で規定する基本文字集合の中の二つの要素\と~は,JIS X 0201 では,それぞれ¥(円

記号)と ̄(オーバライン)に置き換える。

英字(letter)は,上で定義した大文字又は小文字とする。この規格での英字には,他の文字(ラテン以

外のアルファベット)は含まない。

国際文字名は,他の文字を表す方法を提供する。

前方参照  国際文字名(6.4.3),注釈(6.4.9),前処理指令(6.10),文字定数(6.4.4.4),文字列(7.1.1),

文字列リテラル(6.4.5

5.2.1.1

3

文字表記  次に示す左側の三つの文字の並び[文字表記(trigraph sequence(

12

)

)という。

]が

ソースファイルの中にある場合,その三つの文字の並びを同じ行の右側の対応する 1 文字に置き換える。

??= #

??(

[

??/

??)

]

??'

^

??<

{

??!

|

??>

}

??-

~

これら以外の 3 文字表記は,存在しない。上に掲げた 3 文字表記の始まりとならない?は,置き換えな

い。

例  次のソース行

printf("Eh???/n");

は,

(3 文字表記??/の置き換え後)

printf("Eh?

\n");

となる。

5.2.1.2

多バイト文字  ソース文字集合は,拡張文字集合の要素を表現するための多バイト文字を含んで

いてもよい。実行文字集合も,多バイト文字を含んでいてもよく,その多バイト文字の表現形式は,ソー

ス文字集合における表現形式と一致していなくてもよい。二つの文字集合は,次の条件を満たさなければ

───────────────────────────────────────────────

(12) 3

文字表記は,7 ビット US ASCII 符号集合の部分集合である ISO/IEC 646 で規定する不変符号集合

に定義がない文字の入力を可能にする。


14

X 3010

:2003 (ISO/IEC 9899:1999)

     

ならない。

−  基本文字集合が存在しなければならず,各文字は,1 バイトとして符号化しなければならない。

−  追加要素が存在するか否か,並びにそれらの意味及び表現は,文化圏固有とする。

−  多バイト文字集合は,

シフト状態に依存した表現形式(state-dependent encoding)をもっていてもよい。

この表現形式では,多バイト文字の並びは

初期シフト状態(initial shift state)で始まり,その並びの中

に特定の多バイト文字が現れたとき文化圏固有のその他の

シフト状態(shift state)に移る。初期シフ

ト状態では,すべての 1 バイト文字は,通常と同じ解釈をもち,シフト状態を変えない。それ以外の

シフト状態で,多バイト文字の並びの中のバイトの列の解釈をどのように行うかは,その位置でのシ

フト状態に依存する。

−  すべてのビットが 0 のバイトは,シフト状態にかかわらずナル文字として解釈しなければならない。

−  すべてのビットが 0 のバイトは,一つの多バイト文字の 2 番目以降のバイトに現れてはならない。

ソースファイルに対しては,次の条件が成立しなければならない。

−  識別子,注釈,文字列リテラル,文字定数及びヘッダ名は,初期シフト状態で始まり,初期シフト状

態で終わらなければならない。

−  識別子,注釈,文字列リテラル,文字定数及びヘッダ名は,有効な多バイト文字の並びで構成しなけ

ればならない。

5.2.2

文字表示の意味  fputc 関数が出力する次の文字が現れる表示装置上の位置を,現表示位置(active

position

)という。表示文字(isprint 関数が真となる文字として定義する。

)を表示装置に書くというこ

とは,現表示位置にその文字の図形表現を表示し,次に現表示位置をその行の次の位置に進めることを意

図する。書込みの方向は,文化圏固有とする。行の最終位置というものが存在して,現表示位置が行の最

終位置にある場合,表示装置の動作は未規定とする。

実行文字集合中の非図形文字を表す英字逆斜線表記は,次に列挙する表示装置上での動作を生じること

を意図する。

\a

警報(alert)聴覚的又は視覚的な警報を生じる。現表示位置の変更を伴わない。

\b

後退(backspace)現表示位置をその行の上で直前の位置に移動する。現表示位置が行の最初の位置に

ある場合,表示装置の動作は未規定とする。

\f

書式送り(form feed)現表示位置を次の論理ページの始まりにおける最初の位置に移動する。

\n

改行(new line)現表示位置を次の行の最初の位置に移動する。

\r

復帰(carriage return)現表示位置をその行の最初の位置に移動する。

\t

水平タブ(horizontal tab)現表示位置をその行における次の水平タブ位置に移動する。現表示位置が定

められた最後の水平タブ位置にある,又はその位置を過ぎている場合,表示装置の動作は未規定とす

る。

\v

垂直タブ(vertical tab)現表示位置を次の垂直タブ位置における最初の位置に移動する。現表示位置が

定められた最後の垂直タブ位置にある,又はその位置を過ぎている場合,表示装置の動作は未規定と

する。

上に掲げた 7 個の英字逆斜線表記は,それぞれ char 型の単一のオブジェクトに格納することができる

処理系定義の一意の値をもたなければならない。テキストファイルにおける外部表現は,内部表現と一致

する必要はなく,この規格の範囲外とする。

前方参照  fputc 関数(7.19.7.3),isprint 関数(7.4.1.8

5.2.3

シグナル及び割込み  関数は,いつシグナルによって中断されてもよいように,シグナル処理ルー


15

X 3010

:2003 (ISO/IEC 9899:1999)

     

チンによって呼び出されてもよいように,

又はその双方が行われてもよいように実現しなければならない。

これらの場合,関数は,それ以前に起動されていて,まだ終了していない呼出しの(中断から復帰後の)

制御の流れ,関数の返却値又は自動記憶域期間をもつオブジェクトを変えることなしに,実現しなければ

ならない。これらすべてのオブジェクトは

関数イメージ(function image)(関数の実行可能な表現を構成

する命令列)とは別に,関数の各呼出しに対応して保持しなければならない。

5.2.4

環境限界  翻訳環境及び実行環境の双方とも,言語翻訳プログラム及びライブラリを制約する。規

格合致処理系における環境限界を 5.2.4.1 及び 5.2.4.2 にまとめる。ライブラリにおける限界は,7.で規定す

る。

5.2.4.1

翻訳限界  処理系は,この箇条に示す(各項目の最後の括弧で囲まれた数値で示す)各限界の出

現をそれぞれ少なくとも一つ含むプログラムのうちの少なくとも一つを翻訳及び実行することができなけ

ればならない(

13

)

−  ブロックの入れ子のレベル数(127)

−  条件付き取込みにおける入れ子のレベル数(63)

−  一つの宣言中の一つの算術型,構造体型,共用体型又は不完全型を修飾するポインタ,配列及び関数

宣言子(の任意の組合せ)の個数(12)

−  一つの完結宣言子における括弧で囲まれた宣言子の入れ子のレベル数(63)

−  一つの完結式における括弧で囲まれた式の入れ子のレベル数(63)

−  内部識別子又はマクロ名において意味がある先頭の文字数[各国際文字名又は各ソース拡張文字は,1

個の文字とみなす。

(63)

−  外部識別子において意味がある先頭の文字数[0000FFFF 以下の短い識別子を表す各国際文字名は,6

個の文字とみなす。00010000 以上の短い識別子を表す各国際文字名は,10 個の文字とみなす。各ソー

ス拡張文字は,

(もしあれば)対応する国際文字名と同じ個数の文字とみなす(

14

)

(31)

−  一つの翻訳単位中における外部識別子数(4095)

−  一つのブロックで宣言されるブロック有効範囲をもつ識別子数(511)

−  一つの前処理翻訳単位中で同時に定義されるマクロ識別子数(4095)

−  一つの関数定義における仮引数の個数(127)

−  一つの関数呼出しにおける実引数の個数(127)

−  一つのマクロ定義における仮引数の個数(127)

−  一つのマクロ呼出しにおける実引数の個数(127)

−  一つの論理ソース行における文字数(4095)

−  (連結後の)単純文字列リテラル又はワイド文字列リテラル中における文字数(4095)

−  (ホスト環境の場合)一つのオブジェクトのバイト数(65535)

−  #include で取り込まれるファイルの入れ子のレベル数(15)

−  一つの switch 文(入れ子になった switch 文を除く)中における case ラベルの個数(1023)

−  一つの構造体又は共用体のメンバ数(1023)

−  一つの列挙体における列挙定数の個数(1023)

───────────────────────────────────────────────

(13)

処理系は,固定的な翻訳限界を課することを,可能な限り避けるのが望ましい。

(14)

“今後の言語の方針”

6.11.3)参照。


16

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  一つのメンバ宣言並びにおける構造体又は共用体定義の入れ子のレベル数(63)

5.2.4.2

数量的限界  処理系は,5.2.4.2 で規定するすべての限界(ヘッダ<limits.h>及び<float.h>

の中で定義される。

)を文書化しなければならない。これ以外に<stdint.h>でも限界を定めている。

前方参照  整数型<stdint.h>(7.18

5.2.4.2.1

整数型の大きさ<limits.h>  次に列挙する値は,#if 前処理指令の中で使用するために適し

た定数式に置き換えなければならない。さらに,CHAR_BIT 及び MB_LEN_MAX に対する値を除き,これ

らの値は,対応する型のオブジェクトだけからなる式が整数拡張に従って変換された場合の型と同じ型を

もつ式に置き換えなければならない。これらの処理系定義の値は,それぞれの項目の右に示してある値と

同じ符号をもち,その値以上の大きさ(絶対値)をもたなければならない。

−  ビットフィールドでない最小のオブジェクト(バイト)におけるビット数

CHAR_BIT

                  8

−  型 signed char のオブジェクトにおける最小値

SCHAR_MIN

               -127

//

− (2

7

−1)

−  型 signed char のオブジェクトにおける最大値

SCHAR_MAX

               +127

//

2

7

−1

−  型 unsigned char のオブジェクトにおける最大値

UCHAR_MAX

                255

//

2

8

−1

−  型 char のオブジェクトにおける最小値

CHAR_MIN

(値は,後で規定する。

−  型 char のオブジェクトにおける最大値

CHAR_MAX

(値は,後で規定する。

−  サポートするロケールに対する一つの多バイト文字の最大バイト数

MB_LEN_MAX

        

        1

−  型 short int のオブジェクトにおける最小値

SHRT_MIN

              -32767

//

− (2

15

−1)

−  型 short int のオブジェクトにおける最大値

SHRT_MAX

              +32767

//

2

15

−1

−  型 unsigned short int のオブジェクトにおける最大値

USHRT_MAX

               65535

//

2

16

−1

−  型 int のオブジェクトにおける最小値

INT_MIN

     -32767

//

− (2

15

−1)

−  型 int のオブジェクトにおける最大値

INT_MAX

              +32767

//

2

15

−  型 unsigned int のオブジェクトにおける最大値

UINT_MAX

               65535

//

2

16

−1

−  型 long int のオブジェクトにおける最小値

LONG_MIN

         -2147483647

//

− (2

31

−)

−  型 long int のオブジェクトにおける最大値

LONG_MAX

         +2147483647

//

2

31

−1

−  型 unsigned long int のオブジェクトにおける最大値


17

X 3010

:2003 (ISO/IEC 9899:1999)

     

ULONG_MAX

          4294967295

//

2

32

−1

−  型 long long int のオブジェクトにおける最小値

LLONG_MIN -9223372036854775807

//

− (2

63

−1)

−  型 long long int のオブジェクトにおける最大値

LLONG_MAX +9223372036854775807

//

2

63

−1

−  型 unsigned long long int のオブジェクトにおける最大値

ULLONG_MAX 18446744073709551615

//

2

64

−1

型 char のオブジェクトの値を式の中で符号付き整数として扱う場合,CHAR_MIN の値は,SCHAR_MIN

の値と同じでなければならず,CHAR_MAX の値は,SCHAR_MAX の値と同じでなければならない。符号無

し整数として扱う場合,CHAR_MIN の値は,0 でなければならず,CHAR_MAX の値は,UCHAR_MAX の値と

同じでなければならない(

15

)

。値 UCHAR_MAX は,2

CHAR_BIT

−1 と等しくなければならない。

前方参照  型の表現(6.2.6),条件付き取込み(6.10.1

5.2.4.2.2

浮動小数点型の特性<float.h>  浮動小数点数の表現に関するモデル及び処理系の浮動小数

点演算についての情報を与える値によって,浮動小数点型の特性を定義する(

16

)

。各浮動小数点型に対する

モデルを定義するために,次のパラメタを使用する。

                                S

符号(±1)

                                b

指数表現の基数又は底(1 より大きい整数)

                                e

指数(最小 e

min

から最大 e

max

までの整数)

                                p

精度(を基数としたときの有効数字部)

                                f

k

                      b

より小さい非負の整数(有効数字部の数字)

浮動小数点数(floating-point number)(x)を次のモデルによって定義する。

å

p

k

k

k

e

b

f

sb

x

1

,

e

min

ee

max

浮動小数点型は,正規化された(normalized)浮動小数点数(x≠0 の場合,f

1

>0

)を保持することができ,

更に,他の種類の浮動小数点数[例えば,正規化できないほど小さな(subnormal)浮動小数点数(x≠0,

e=e

min

f

1

=0

,及び正規化されていない(unnormalized)浮動小数点数(x≠0,e>e

min

f

1

=0

]及び浮動小

数点数ではない値(例えば,無限大及び NaN)が保持できてもよい。NaN は,非数(Not-a-Number)を意

味する表現形式とする。qNaN(quiet NaN)は,浮動小数点例外を生成することなく,ほとんどすべての

算術演算を通して伝ぱ(播)する。sNaN(signaling NaN)は,算術オペランドとして現れる場合,一般的

に浮動小数点例外を生成する(

17

)

浮動小数点演算(+,-,*,/)の正確度,並びに<math.h>及び<complex.h>の中で定義する(浮動

小数点型の結果を返却する)ライブラリ関数の正確度は,処理系定義とする。処理系は,正確度は不明,

と規定してもよい。

───────────────────────────────────────────────

(15)

6.2.5

参照。

(16)

この浮動小数点型のモデルは,浮動小数点数の各特性の規定を明確にすることを意図したものであ

り,処理系の浮動小数点演算の実現法がこのとおりであることを要求するものではない。

(17)

IEC 60559:1989

が,

qNaN

及び sNaN を規定している。

IEC 60559:1989

をサポートしない処理系では,

qNaN

及び sNaN は,これらと同じ動作となる表現形式を適用することを意図している。


18

X 3010

:2003 (ISO/IEC 9899:1999)

     

<float.h>

ヘッダの中で定義するすべての整数値は,FLT_ROUNDS を除き,#if 前処理指令の中で使

用するために適した定数式でなければならない。<float.h>ヘッダの中で定義するすべての浮動小数点数

の値は,定数式でなければならない。DECIMAL_DIG,FLT_EVAL_METHOD,FLT_RADIX 及び FLT_ROUNDS

を除くすべては,三つの浮動小数点型それぞれに対し別個の名前をもつ。FLT_EVAL_METHOD 及び

FLT_ROUNDS

を除くすべての値に対し,浮動小数点型のモデルにおける表現が与えられる。

浮動小数点加算の丸めモードは,

FLT_ROUNDS

の処理系定義の値によって次のとおり特徴付けられる(

18

)

-1

不確定

  0

0

の方向へ

  1

最も近い値へ

  2

正の無限大の方向へ

  3

負の無限大の方向へ

FLT_ROUNDS

に対するその他の値は,処理系定義の丸め動作を特徴付ける。

浮動小数点型のオペランドをもつ演算の結果の値,通常の算術型変換の結果の値,及び浮動小数点定数

の値は,その型に対する要求よりも大きな範囲と精度をもつ形式で評価してもよい。どのような評価形式

を使うかは,FLT_EVAL_METHOD の処理系定義の値によって次のとおり特徴付けられる(

19

)

-1

不確定

  0

すべての演算及び定数を,その型の範囲及び精度のとおりに評価する

  1

型 float 及び型 double の演算及び定数を,型 double の範囲及び精度で評

価し,型 long double の演算及び定数を,型 long double の範囲及び精

度で評価する

  2

すべての演算及び定数を,型 long double の範囲及び精度で評価する

FLT_EVAL_METHOD

に対するその他の負の値は,処理系定義の動作を特徴付ける。

次に列挙する値は,それぞれの項目の行の右に示してある値と同じ符号,及びその値以上の絶対値をも

つ処理系定義の値を表す定数式で置き換えなければならない。

−  指数表現における基数 b

FLT_RADIX

2

−  浮動小数点数の有効数字部(FLT_RADIX を基数とする。

)のけた数 p

FLT_MANT_DIG

DBL_MANT_DIG

LDBL_MANT_DIG

−  次の条件を満たす 10 進数のけた数 nを基数とする p

max

けたの数字をもつ(処理系がサポートする

最大の精度をもつ浮動小数点型の)浮動小数点数は,けたの 10 進数の浮動小数点数に丸めることが

でき,それを正確に元の値に戻すことができる。は,次の式で与えられる。

───────────────────────────────────────────────

(18)

FLT_ROUNDS

の値は,<fenv.h>の中の関数 fesetround による丸めモードの実行時の変更に伴

って変わる。

(19)

評価方法は,実数型だけではなくすべての浮動小数点型の式の評価形式を決定する。例えば,

FLT_EVAL_METHOD

が 1 の場合,二つの float _Complex オペランドの積は,double

 _Complex

形式で表現し,その実部と虚部は,それぞれ double で評価する。


19

X 3010

:2003 (ISO/IEC 9899:1999)

     

p

max

log

10

b

b

が 10 のべき乗の場合

é1+p

max

log

10

b

ù

それ以外の場合

DECIMAL_DIG

10

−  次の条件を満たす 10 進数のけた数 qけたの 10 進数の浮動小数点数は,を基数とする けたの浮

動小数点数に丸めることができ,それを正確に元の けたの 10 進数に戻すことができる。は,次の

式で与えられる。

log

10

b

b

が 10 のべき乗の場合

ë(p−1) log

10

b

û

それ以外の場合

FLT_DIG  6

 DBL_DIG  10

LDBL_DIG

10

−  FLT_RADIX をその値から 1 減算した値でべき乗したとき,正規化された浮動小数点数となる最小の

負の整数 e

min

FLT_MIN_EXP

DBL_MIN_EXP

LDBL_MIN_EXP

− 10 をその値でべき乗したとき,正規化された浮動小数点数の範囲内の値となる最小の負の整数。次の

式で与えられる。

ë

1

10

min

log

e

b

û

FLT_MIN_10_EXP -37

 DBL_MIN_10_EXP -37

LDBL_MIN_10_EXP

-37

FLT_RADIX

をその値から

1

減算した値でべき乗したとき,表現可能な有限の浮動小数点数となる最

大の整数

e

max

FLT_MAX_EXP

DBL_MAX_EXP

LDBL_MAX_EXP

 10

をその値でべき乗したとき,表現可能な有限の浮動小数点数の範囲内の値となる最大の整数。次の

式で与えられる。

ë

)

)

1

((

log

max

10

e

p

b

b

û

FLT_MAX_10_EXP +37

 DBL_MAX_10_EXP +37

LDBL_MAX_10_EXP

+37

次に列挙する値は,それぞれの項目の行の右に示してある値以上の処理系定義の値をもつ定数式で置き

換えなければならない。

表現可能な最大の有限浮動小数点数

max

)

1

(

e

p

b

b

FLT_MAX  1E+37

 DBL_MAX  1E+37

LDBL_MAX

1E+37

次に列挙する値は,それぞれの項目の行の右に示してある値以下の処理系定義の(正の)値をもつ定数


20

X 3010

:2003 (ISO/IEC 9899:1999)

     

式で置き換えなければならない。

与えられた浮動小数点型で表現可能な

1

より大きい最小の値と

1

との差

b

1

p

FLT_EPSILON

1E-5

DBL_EPSILON

1E-9

LDBL_EPSILON

1E-9

最小の正規化された正の浮動小数点数

1

min

e

b

FLT_MIN  1E-37

 DBL_MIN  1E-37

LDBL_MIN

1E-37

推奨実装仕様  double から DECIMAL_DIG けたの

10

進数字へ変換し,続いて逆変換した結果は,元の値

と等しくなることが望ましい。

1.

この規格の最低限の要求に適合する人工的な浮動小数点表現,及び型 float に対するヘッダ

<float.h>

内の適切な値を次に示す。

å

6

1

16

16

k

k

k

e

f

s

x

,

31

e

≦+32

FLT_RADIX

16

   FLT_MANT_DIG

  6

   FLT_EPSILON

  9.53674316E-07F

 FLT_DIG  6

   FLT_MIN_EXP

  -31

 FLT_MIN  2.93873588E-39F

   FLT_MIN_10_EXP  -38

   FLT_MAX_EXP

  +32

 FLT_MAX  3.40282347E+38F

   FLT_MAX_10_EXP  +38

2.  IEC 60559(

20

)

での単精度正規化数及び倍精度正規化数に対する要求にも適合する浮動小数点表

現,及び型 float と型 double に対する<float.h>ヘッダ内の適切な値を次に示す。

å

24

1

2

2

k

k

k

e

f

f

s

x

,

125

e

≦+128

å

53

1

2

2

k

k

k

e

d

f

s

x

,

1021

e

≦+1024

FLT_RADIX 2

 DECIMAL_DIG

17

 FLT_MANT_DIG

24

 FLT_EPSILON

1.19209290E-07F

//

10

進定数

FLT_EPSILON 0X1P-23F

//

16

進定数

───────────────────────────────────────────────

(20)

IEC 60559

での浮動小数点型のモデルでは,

b

の 0 乗からのべき乗の和であるので,

指数の限界値は,

ここに示すものより 1 小さい。


21

X 3010

:2003 (ISO/IEC 9899:1999)

     

FLT_DIG 6

 FLT_MIN_EXP

-125

 FLT_MIN  1.17549435E-38F

//

10

進定数

FLT_MIN 0X1P-126F  //

16

進定数

FLT_MIN_10_EXP -37

 FLT_MAX_EXP

+128

 FLT_MAX  3.40282347E+38F

//

10

進定数

FLT_MAX 0X1.fffffeP127F

//

16

進定数

FLT_MAX_10_EXP +38

 DBL_MANT_DIG

53

 DBL_EPSILON

2.2204460492503131E-16

//

10

進定数

DBL_EPSILON 0X1P-52

//

16

進定数

DBL_DIG 15

 DBL_MIN_EXP

-1021

 DBL_MIN  2.2250738585072014E-308

//

10

進定数

DBL_MIN 0X1P-1022  //

16

進定数

DBL_MIN_10_EXP -307

 DBL_MAX_EXP

+1024

 DBL_MAX  1.7976931348623157E+308

//

10

進定数

DBL_MAX 0X1.fffffffffffffP1023

//

16

進定数

DBL_MAX_10_EXP +308

double

より大きな型をサポートする場合,DECIMAL_DIG は,17 より大きい。例えば,最も

大きな型が,最小幅の IEC 60559(精度が 64 ビットの)拡張倍精度(double-extended)形式を

使う場合,DECIMAL_DIG は,21 になる。

前方参照  条件付き取込み(6.10.1),数学<math.h>(7.12),複素数計算<complex.h>(7.3),浮動小数

点環境<fenv.h>(7.6

6.

言語

6.1

記法  6.で用いる構文の記法では,構文要素(非終端記号)は英数字を含む日本語で示し,プログラ

ムにそのまま用いられるリテラル語及び文字集合の要素(終端記号)は英数字及び特殊記号で示す。非終

端記号に続くコロン(:)は,その後に非終端記号の定義があることを示す。幾つかの定義が別々の行に

表示されている場合,又は“次のいずれか”と前置きしている場合,それらのうちの一つを選択すること

を意味する。省略可能な記号は,添字“

opt

”で示す。したがって,

{

opt

 }

は,波括弧の中に省略可能な式があることを示す。

言語の構文の要約を

附属書 に記す。

6.2

概念

6.2.1

識別子の有効範囲  識別子は,次のいずれか一つを表す。

−  オブジェクト

−  関数


22

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  構造体,共用体,又は列挙体のタグ又はメンバ

−  型定義名

−  ラベル名

−  マクロ名

−  マクロ仮引数

同一の識別子であっても,プログラム内の異なる位置では異なる実体を表すことがある。列挙体のメンバ

列挙定数(enumeration constant)と呼ぶ。プログラム翻訳の意味解析フェーズより前に,ソースファイ

ル中のすべてのマクロ名の出現を,そのマクロ定義を構成する前処理字句列で置き換えるから,以下では

マクロ名とマクロ仮引数を考慮しない。

識別子が指し示すそれぞれの異なる実体について,識別子は,

有効範囲(scope)と呼ぶプログラムテキ

ストの範囲にあるときだけ,

可視(visible)(すなわち,使用可能)とする。同じ識別子が異なる実体を指

し示すのは,それらが異なる有効範囲をもつときか,又は異なる名前空間に属するときかのいずれかとす

る。有効範囲は,関数,ファイル,ブロック及び関数原型の 4 種類とする。

関数原型(function prototype)

は,その仮引数の型を宣言する関数の宣言とする。

ラベル名は,

関数有効範囲(function scope)をもつ唯一の種類の識別子とする。ラベル名は,それが現

れる関数のどこでも(goto 文の中で)使用でき,

(:と文が続く)その構文の出現によって,暗黙に宣言

される。

その他の各識別子は,それらの(宣言子又は型指定子における)宣言の位置によって定められる有効範

囲をもつ。

識別子を宣言する宣言子又は型指定子がどのブロック又は仮引数並びよりも外側に現れる場合,

その識別子は

ファイル有効範囲(file scope)をもち,その範囲は翻訳単位の最後で終了する。識別子を宣

言する宣言子又は型指定子がブロックの中又は関数定義の仮引数宣言並びに現れる場合,その識別子は

ロック有効範囲(block scope)をもち,その範囲は対応するブロックの最後で終了する。識別子を宣言す

る宣言子又は型指定子が(関数定義の一部ではない)関数原型の中の仮引数宣言並びに現れる場合,その

識別子は

関数原型有効範囲(function prototype scope)をもち,その範囲は関数宣言子の最後で終了する。

識別子が同一の名前空間で二つの異なる実体を指し示す場合,それらの有効範囲は重なることがある。こ

の場合,一方の実体の有効範囲[

内側の有効範囲(inner scope)]は,もう一方の実体の有効範囲[外側の

有効範囲(outer scope)]の真部分集合となる。内側の有効範囲の中では,識別子は内側の有効範囲で宣言

された実体を指し示し,外側の有効範囲で宣言された実体は,内側の有効範囲の中では

隠される(hidden)

(すなわち,不可視となる。

明示的に異なる規定を行わない限り,この規格が“識別子”という用語をある実体(構文の構成要素と

してではなく)を参照するために用いる場合,それは,その識別子が出現した位置においてその宣言が可

視である実体(関連する名前空間に属するもの)を参照しているものとする。

二つの識別子は,有効範囲が同じ位置で終わる場合,そしてその場合に限り,同じ有効範囲(same scope)

をもつという。

構造体,共用体及び列挙体のタグは,そのタグを宣言する型指定子中のタグの出現の直後から始まる有

効範囲をもつ。各々の列挙定数は,列挙子並びの中にその列挙定数を定義する列挙子が出現した直後から

始まる有効範囲をもつ。それ以外のすべての識別子は,その宣言子の完了の直後から始まる有効範囲をも

つ。

前方参照  関数定義(6.9.1),関数呼出し(6.5.2.2),識別子(6.4.2),識別子の名前空間(6.2.3),宣言(6.7),

ソースファイル取込み(6.10.2

,文(6.8

,マクロ置き換え(6.10.3


23

X 3010

:2003 (ISO/IEC 9899:1999)

     

6.2.2

識別子の結合  異なる有効範囲で又は同じ有効範囲で 2 回以上宣言された識別子は,結合(linkage)

(

21

)

と呼ぶ過程によって,同じオブジェクト又は関数を参照することができる。結合は,外部結合,内部結

合及び無結合の 3 種類とする。

プログラム全体を構成する翻訳単位及びライブラリの集合の中で,

外部結合(external linkage)をもつ一

つの識別子の各々の宣言は,同じオブジェクト又は関数を表す。一つの翻訳単位の中で,

内部結合(internal

linkage

)をもつ一つの識別子の各々の宣言は,同じオブジェクト又は関数を表す。

無結合(no linkage)を

もつ識別子の各々の宣言は,それぞれが別々の実体を表す。

オブジェクト又は関数に対するファイル有効範囲の識別子の宣言が記憶域クラス指定子 static を含む

場合,その識別子は,内部結合をもつ(

22

)

識別子が,その識別子の以前の宣言が可視である(

23

)

有効範囲において,記憶域クラス指定子 extern を

伴って宣言される場合,次のとおりとする。

−  以前の宣言において内部結合又は外部結合が指定されているならば,新しい宣言における識別子は,

以前の宣言と同じ結合をもつ。

−  可視である以前の宣言がない場合,又は以前の宣言が無結合である場合,この識別子は外部結合をも

つ。

関数の識別子の宣言が記憶域クラス指定子をもたない場合,その結合は,記憶域クラス指定子 extern

を伴って宣言された場合と同じ規則で決定する。

オブジェクトの識別子の宣言がファイル有効範囲をもち,

かつ記憶域クラス指定子をもたない場合,その識別子の結合は,外部結合とする。

オブジェクト又は関数以外を宣言する識別子,関数仮引数を宣言する識別子,及び記憶域クラス指定子

extern

を伴わないブロック有効範囲のオブジェクトを宣言する識別子は,無結合とする。

翻訳単位の中で同じ識別子が内部結合と外部結合の両方で現れた場合,その動作は未定義とする。

前方参照  外部定義(6.9),式(6.5),宣言(6.7),文(6.8

6.2.3

識別子の名前空間  翻訳単位中のある位置で特定の識別子の複数の宣言が可視である場合,構文的

な文脈によって異なった実体への参照を区別する。すなわち,識別子を様々に分類するため,次に示す種

類の

名前空間(name space)が存在する。

ラベル名(label name)(ラベルの宣言及び使用の構文によって区別する。)。

−  構造体,共用体及び列挙体の

タグ(tag)(先行するキーワード struct,union 又は enum(

24

)

によっ

て区別する。

−  構造体又は共用体の

メンバ(member)。構造体又は共用体の各々は,そのメンバに対する別個の名前

空間をもつ(.演算子又は->演算子を使ってメンバをアクセスするのに使用される式の型によって区

別する。

−  その他のすべての識別子(通常の宣言子で宣言されたもの,又は列挙定数として宣言されたもの)

。こ

───────────────────────────────────────────────

(21)

異なる識別子の間で結合が行われることはない。

(22)

関数宣言が記憶域クラス指定子 static をもつことができるのは,ファイル有効範囲をもつ宣言の

場合だけである(6.7.1 参照)

(23)

新しい宣言は以前の宣言を隠すことがある(6.2.1 参照)

(24)

タグ名の名前空間を三つとすることも考えられるが,この規格ではただ一つの名前空間が存在する

ことにしている。


24

X 3010

:2003 (ISO/IEC 9899:1999)

     

れらを

通常の識別子(ordinary identifier)と呼ぶ。

前方参照  goto 文(6.8.6.1),構造体指定子及び共用体指定子(6.7.2.1),構造体及び共用体のメンバ(6.5.2.3),

タグ(6.7.2.3

,ラベル付き文(6.8.1

,列挙型指定子(6.7.2.2

6.2.4

オブジェクトの記憶域期間  オブジェクトは,その生存期間を決定する記憶域期間(storage

duration

)をもつ。記憶域期間は,静的記憶域期間,自動記憶域期間,及び割付け記憶域期間の 3 種類とす

る。割付け記憶域は 7.20.3 で規定する。

オブジェクトの

生存期間(lifetime)とは,オブジェクトに対して記憶域の確保が保証されている,プロ

グラム実行の一部分をいう。オブジェクトは,生存期間を通じて存在し,一定のアドレス(

25

)

をもち,最後

に格納された値を保持する(

26

)

。オブジェクトを生存期間の外部で参照したときの動作は未定義とする。ポ

インタの値は,そのポインタが指すオブジェクトが生存期間の最後に到達すると,不定になる。

外部結合若しくは内部結合をもつか,又は記憶域クラス指定子 static を使って宣言された識別子のオ

ブジェクトは,

静的記憶域期間(static storage duration)をもつ。その生存期間はプログラム実行の全体と

する。その値はプログラム開始処理の前に 1 回だけ初期化する。

無結合をもち,かつ記憶域クラス指定子 static をもたずに宣言された識別子のオブジェクトは,

自動

記憶域期間(automatic storage duration)をもつ。

可変長配列型をもたず,自動記憶域期間をもつオブジェクトの生存期間は,オブジェクトが関連付けら

れているブロックに入る時から,どのような形であれ,そのブロックの実行が終了する時までとする。

(内

側のブロックに入ったり,又は関数を呼び出したりした場合,そのブロックの実行は一時停止するが,終

了はしない。

)ブロックに再帰的に入るごとに,オブジェクトの新しい実体を生成する。オブジェクトの初

期値は不定とする。オブジェクトの初期化が指定されている場合,ブロックの実行がその宣言に到達する

ごとに,初期化を行う。初期化が指定されていない場合,その宣言に到達するごとに,オブジェクトの値

を不定にする。

可変長配列型をもち,

自動記憶域期間をもつオブジェクトの生存期間は,

オブジェクトの宣言の時から,

プログラムの実行が宣言の有効範囲から離れる時までとする(

27

)

。有効範囲に再帰的に入るごとに,オブジ

ェクトの新しい実体を生成する。オブジェクトの初期値は不定とする。

前方参照  関数呼出し(6.5.2.2),初期化(6.7.8),宣言子(6.7.5),配列宣言子(6.7.5.2),文(6.8

6.2.5

型  オブジェクトに格納した値又は関数の返す値の意味は,それをアクセスするのに使われる式の

型(type)によって決定する。(オブジェクトとして宣言された識別子は最も単純な式とし,その型は識別

子の宣言において指定された型とする。

)型は,

オブジェクト型(object type)(オブジェクトを完全に規定

する型)

関数型(function type)(関数を規定する型),及び不完全型(incomplete type)(オブジェクトを

規定する型で,その大きさを確定するのに必要な情報が欠けたもの)に分類する。

型_Bool として宣言されたオブジェクトは,値 0 及び 1 を格納するのに十分な大きさをもつ。

───────────────────────────────────────────────

(25)

“一定のアドレス”とは,オブジェクトへのポインタの(場合によっては異なる時における)二つ

の生成に関して,二つのポインタを比較して等しいことを意味する。同じプログラムの二つの異な

る実行については,アドレスが異なることもありうる。

(26)

ボラタイルオブジェクトの場合,最後の格納はプログラム中で明示的でないかもしれない。

(27)

宣言を含む最も内側のブロックを離れると,又はそのブロック若しくは更に内側のブロックで,宣

言より前の位置に移動すると,宣言の有効範囲から離れる。


25

X 3010

:2003 (ISO/IEC 9899:1999)

     

型 char として宣言されたオブジェクトは,実行基本文字集合の任意の要素を格納するのに十分な大き

さをもつ。実行基本文字集合の任意の要素を char 型のオブジェクトに格納した場合,その値は非負であ

ることを保証する。その他の文字を char 型のオブジェクトに格納した場合,その結果の値は処理系定義

とするが,その型で表現可能な値の範囲に含まれなければならない。

標準符号付き整数型(standard signed integer type)は,signed char,short int,int,long int

及び long long int の 5 種類とする。

[これらの型及び他の型は幾つかの別の方法で指定してもよい

6.7.2 で規定する。

]さらに,処理系定義の

拡張符号付き整数型(extended signed integer type)(

28

)

を処

理系が提供してもよい。標準符号付き整数型及び拡張符号付き整数型を総称して

符号付き整数型(signed

integer type

)と呼ぶ(

29

)

型 signed char として宣言されたオブジェクトは,

“単なる”char 型のオブジェクトと同じ大きさの

記憶域を占有する。

“単なる”int 型のオブジェクトは,実行環境のアーキテクチャによって決まる自然

な(ヘッダ<limits.h>に定義される INT_MIN から INT_MAX までの範囲にある任意の値を格納するのに

十分な)大きさをもつ。

符号付き整数型の各々に対応するが,

それとは異なる符号無し整数型が存在する

(キーワード unsigned

で示される)

。符号無し整数型は,符号付き整数型と(符号情報を含めて)同じ大きさの記憶域を使い,か

つ同じ境界調整要求をもつ。型_Bool,及び標準符号付き整数型に対応する符号無し整数型は,

標準符号

無し整数型(standard unsigned integer type)とする。拡張符号付き整数型に対応する符号無し整数型は,拡

張符号無し整数型(extended unsigned integer type)とする。標準符号無し整数型及び拡張符号無し整数型を

総称して

符号無し整数型(unsigned integer type)と呼ぶ(

30

)

標準符号付き整数型及び標準符号無し整数型を総称して

標準整数型(standard integer type)と呼び,拡張

符号付き整数型及び拡張符号無し整数型を総称して

拡張整数型(extended integer type)と呼ぶ。

二つの整数型が,符号の有無に関して同じであり,整数変換の順位(6.3.1.1 参照)に関して異なる場合,

整数変換の順位が低い型の値の範囲は,もう一方の型の値の範囲の部分集合とする。

符号付き整数型の負でない値の範囲は,対応する符号無し整数型の範囲の部分集合とし,二つの型にお

いて同じ値の表現は同じとする(

31

)

。符号無しオペランドを含む計算は,決してオーバフローしない。すな

わち,結果を符号無し整数型で表現できないときは,その型で表現しうる最大値より 1 だけ大きい数を法

とする剰余を結果とする。

実浮動小数点型(real floating type)は,float,double 及び long double(

32

)

の 3 種類とする。型

float

の値の集合は,型 double の値の集合の部分集合とする。型 double の値の集合は,型 long

───────────────────────────────────────────────

(28)

処理系定義のキーワードは,どのような目的のためにも予約された識別子の形式(7.1.3 で規定す

る。

)をもたなければならない。

(29)

したがって,この規格において符号付き整数型に関するすべての記述を,拡張符号付き整数型にも

適用する。

(30)

したがって,この規格において符号無し整数型に関するすべての記述を,拡張符号無し整数型にも

適用する。

(31)

二つの型において,値の表現と境界調整要求が同じであれば,関数の引数として,関数からの返却

値として,又は共用体のメンバとして,両方の値が交換可能であることを意味する。

(32)

“今後の言語の方針”

6.11.1 参照)


26

X 3010

:2003 (ISO/IEC 9899:1999)

     

double

の値の集合の部分集合とする。

複素数型(complex type)は,float _Complex,double _Complex 及び long double _Complex

の 3 種類とする(

33

)

。実浮動小数点型及び複素数型を総称して

浮動小数点型(floating type)と呼ぶ。

それぞれの浮動小数点型に対して,

対応する実数型(corresponding real type)が存在し,それは常に実浮

動小数点型とする。実浮動小数点型に対しては,同じ型を対応する実数型とする。複素数型に対しては,

型名からキーワード_Complex を除いた型を,対応する実数型とする。

それぞれの複素数型は,対応する実数型の(正確に)二つの要素をもつ配列型と同じ表現及び境界調整

要求をもつ。この配列の最初の要素は複素数の実部に等しく,第 2 の要素は虚部に等しい。

型 char,符号付き整数型,符号無し整数型及び浮動小数点型を総称して

基本型(basic type)と呼ぶ。

たとえ,処理系が二つ以上の基本型を同じ表現で定義しても,これらは異なった型とする(

34

)

三つの型 char,signed char 及び unsigned char を総称して

文字型(character type)と呼ぶ。処理

系は,char を,signed char 又は unsigned char のいずれかと同じ値の範囲,同じ表現形式,そし

て同じ動作をするものとして定義しなければならない(

35

)

列挙体(enumeration)は,名前付けられた整数定数値から成る。それぞれの列挙体は,異なる列挙型

(enumerated type)を構成する。

型 char,符号付き整数型,符号無し整数型,及び列挙型を総称して

整数型(integer type)と呼ぶ。整数

型及び実浮動小数点型を総称して

実数型(real type)と呼ぶ。

整数型及び浮動小数点型を総称して

算術型(arithmetic type)と呼ぶ。それぞれの算術型は,一つの型領

域(type domain)に属する。実数型領域(real type domain)は実数型から成り,複素数型領域(complex type

domain

)は複素数型から成る。

void

型の値の集合は空とする。それは,完全にすることのできない不完全型とする。

派生型(derived type)は,オブジェクト型,関数型及び不完全型から幾つでも構成することができる。

派生型の種類は,次のとおりとする。

配列型(array type)は,要素型(element type)と呼ぶ特定のメンバオブジェクト型をもつ空でないオ

ブジェクトの集合を連続して割り付けたものを表す(

36

)

。配列型は,その要素型及び配列の要素の個数

によって特徴付ける。配列型はその要素型から派生されるといい,要素型が

T

の場合,配列型は“

T

の配列”と呼ぶ。要素型から配列型を構成することを“配列型派生”と呼ぶ。

構造体型(structure type)は,メンバオブジェクト(ある状況では,不完全配列)の空でない集合を順

───────────────────────────────────────────────

(33)

虚数型の仕様については,

附属書 G(参考)で示す。

(34)

処理系においては,基本型又は他の型を示すための別の方法としての新しいキーワードを定義して

よい。これは,すべての基本型は異ならなければならないという要求には違反しない。処理系定義

のキーワードは,どのような目的のためにも予約された識別子の形式(7.1.3 で規定する。

)をもた

なければならない。

(35)

<limits.h>

で定義される CHAR_MIN は,0 又は SCHAR_MIN のいずれかの値をとる。これにより,

signed char

と unsigned char のいずれを選択したかを区別することができる。いずれを選択

したとしても,char は signed char や unsigned char とは異なる型であり,いずれとも適合

しない。

(36)

オブジェクト型は不完全型を含まないので,不完全型の配列は作ることができない。


27

X 3010

:2003 (ISO/IEC 9899:1999)

     

に割り付けたものを表す。各メンバは,名前を指定してもよく異なる型をもってもよい。

共用体型(union type)は,重なり合って割り付けたメンバオブジェクトの空でない集合を表す。各メ

ンバは,名前を指定してもよく異なる型をもってもよい。

関数型(function type)は,指定された返却値の型をもつ関数を表す。関数型は,その返却値の型,並

びにその仮引数の個数及び型によって特徴付ける。

関数型は,

その返却値の型から派生されるといい,

返却値の型が

T

の場合,関数型は“

T

を返す関数”と呼ぶ。返却値の型から関数型を構成することを

“関数型派生”と呼ぶ。

ポインタ型(pointer type)は,被参照型(referenced type)と呼ぶ関数型,オブジェクト型又は不完全

型から派生することができる。ポインタ型は,被参照型の実体を参照するための値をもつオブジェク

トを表す。被参照型

T

から派生されるポインタ型は,

T

へのポインタ”と呼ぶ。被参照型からポイン

タ型を構成することを“ポインタ型派生”と呼ぶ。

派生型を構成するこれらの方法は,再帰的に適用できる。

算術型及びポインタ型を総称して,

スカラ型(scalar type)と呼ぶ。配列型及び構造体型を総称して集成

体型(aggregate type)と呼ぶ(

37

)

大きさの分からない配列型は,不完全型とする。その型は,それ以降のその型の識別子の宣言(内部結

合又は外部結合をもつ)で大きさを指定することによって,完全となる。内容の分からない構造体型又は

共用体型(6.7.2.3 で規定)は,不完全型とする。その型は,同じ有効範囲のそれ以降の同じ構造体タグ又

は共用体タグの宣言で,内容を定義することによって,その型のすべての宣言に関し完全となる。

配列型,関数型及びポインタ型を総称して

派生宣言子型(derived declarator type)と呼ぶ。型

T

からの

言子型派生(declarator type derivation)とは,型

T

に配列型派生,関数型派生又はポインタ型派生を適用し

て,型

T

から派生宣言子型を構成することをいう。

型は,その

型分類(type category)によって特徴付ける。型分類とは,型が派生型を含む場合,(この箇

条の派生型の構成において規定したとおり)最も外側の派生とし,型が派生型を含まない場合,その型自

身とする。

ここまでに定めた型を,

非修飾型(unqualified type)と呼ぶ。各非修飾型は,const,volatile,及び

restrict

修飾子の一つ,二つ又は三つの組合せに対応する各種の

修飾版(qualified version)をもつ(

38

)

一つの型の修飾版と非修飾版は,同じ型分類,同じ表現及び同じ境界調整要求をもつが,異なる型とする

(

39

)

。型修飾子をもつ型から派生したとしても,派生型はその型修飾子によって修飾されない。

void

へのポインタは,文字型へのポインタと同じ表現及び同じ境界調整要求をもたなければならない

(

39

)

。同様に,適合する型へのポインタ同士の場合,修飾版であるか又は非修飾版であるかにかかわらず,

同じ表現及び同じ境界調整要求をもたなければならない。構造体型へのポインタは,すべて同じ表現及び

同じ境界調整要求をもたなければならない。共用体型へのポインタは,すべて同じ表現及び同じ境界調整

要求をもたなければならない。これ以外の型へのポインタは,同じ表現又は同じ境界調整要求をもつ必要

───────────────────────────────────────────────

(37)

集成体型には共用体型が含まれないことに注意する。共用体型のオブジェクトは,どの時点でもた

だ一つのメンバしか含まないからである。

(38)

修飾された配列型及び関数型については,6.7.3 参照。

(39)

二つの型において,値の表現と境界調整要求が同じであれば,関数の引数として,関数からの返却

値として,又は共用体のメンバとして,両方の値が交換可能であることを意味する。


28

X 3010

:2003 (ISO/IEC 9899:1999)

     

はない。

1.  “float *”として表された型は,“float へのポインタ”型である。その型分類はポインタ

であり,浮動小数点型ではない。この型の const 修飾版は,

“float * const”として表すこ

とができる。

これに対して

“const float *”

と表された型は,

修飾型ではなく,

それは   “const

修飾された float へのポインタ”

,すなわち修飾型へのポインタである。

2.  “struct tag (*[5])(float)”として表された型は,“struct tag を返す関数へのポイ

ンタの配列”である。配列は長さ 5 をもち,関数は,float 型の引数を 1 個もつ。この型の型

分類は,配列である。

前方参照  宣言(6.7),適合型及び合成型(6.2.7

6.2.6

型の表現

6.2.6.1

一般的規定  すべての型の表現は,6.2.6 に規定されているものを除き,未規定とする。

ビットフィールドの場合を除き,オブジェクトは 1 バイト以上の連続した並びから成る。その並びのバ

イト数,バイトの順序,及び表現方法は,明示的に規定するか,又は処理系定義とする。

符号無しビットフィールド及び unsigned char 型のオブジェクトに格納した値は,純粋 2 進表現を

用いて表現しなければならない(

40

)

ビットフィールド以外のオブジェクト(unsigned char 型以外の型をもつ)に格納した値は,

n

をこ

の型のオブジェクトのバイト単位の大きさとして,

n

×CHAR_BIT 個のビットで表す。この値を unsigned

char [

n

]

型のオブジェクトに(例えば,memcpy を用いて)コピーすることができる。コピーした結果

のバイトの集合を,この値の

オブジェクト表現(object representation)と呼ぶ。ビットフィールドに指定し

た大きさを

m

とすると,ビットフィールドに格納する値は,

m

ビットから成る。そのオブジェクト表現は,

ビットフィールドを保持しているアドレス指定可能な記憶域単位に格納された,ビットフィールドを構成

する

m

個のビットの集合とする。NaN を除き,同じオブジェクト表現をもつ二つの値の比較の結果は等し

い。ただし,比較の結果が等しい値が,異なるオブジェクト表現をもってもよい。

オブジェクト表現の中には,そのオブジェクト型の値を表現しないものがある。オブジェクトに格納し

た値がオブジェクト型の値を表現せず,文字型ではない左辺値式でそれを読み取る場合,その動作は未定

義とする。文字型ではない左辺値式の副作用(その結果,オブジェクトのすべて又は一部が変更される。

によって,オブジェクト型の値を表現しないオブジェクト表現が生成される場合,その動作は未定義とす

る(

41

)

。オブジェクト型の値を表現しないオブジェクト表現を

トラップ表現(trap representation)と呼ぶ。

値を構造体型又は共用体型のオブジェクトに格納する場合,

メンバオブジェクトに含まれる部分も含め,

オブジェクト表現の詰め物バイトに対応するバイトの値は未規定とする(

42

)

。詰め物バイトの値は,そのオ

───────────────────────────────────────────────

(40) 0

と 1 の 2 進数字を用いる,位置に基づく記数法。この値は,連続したビットについて,1 で始まる

2

のべき乗をそれぞれ乗じ,合計する。ただし,最上位ビットは別扱いとなりうる。(

American 

National Dictionary for Information Processing Systems

から引用。

)1 バイトは CHAR_BIT 個のビットか

ら成り,unsigned char 型の値の範囲は 0 から 2

CHAR_BIT

1

までである。

(41)

したがって,自動変数は,未定義な動作を起こすことなく,トラップ表現で初期化することが可能

である。この場合,この変数の値は,適切な値が格納されるまでは使用できない。

(42)

したがって,処理系は例えば構造体の代入について,要素を 1 個ずつ代入する方法を用いてもよい

し,memcpy を用いる方法を用いてもよい。


29

X 3010

:2003 (ISO/IEC 9899:1999)

     

ブジェクトの値がトラップ表現であるかどうかに影響を与えてはならない。構造体又は共用体オブジェク

トのビットで,ビットフィールドメンバと同じバイトに属するが,そのメンバの一部ではないビットも,

同様に,そのオブジェクトの値がトラップ表現であるかどうかに影響を与えてはならない。

値を共用体型のオブジェクトのメンバに格納すると,このメンバに対応せず,他のメンバに対応するオ

ブジェクト表現のバイトの値は未規定とする。しかし,共用体オブジェクトの値が,それによってトラッ

プ表現となってはならない。

二つ以上のオブジェクト表現をもつ値に演算子を適用する場合,いずれのオブジェクト表現が用いられ

るかが,結果の値に影響を及ぼしてはならない(

43

)

。ある値に対して二つ以上のオブジェクト表現をもつ型

を用いて,その値をオブジェクトに格納する場合,どの表現が用いられるかは未規定とする。しかしトラ

ップ表現が生成されてはならない。

前方参照  左辺値,配列及び関数指示子(6.3.2.1),式(6.5),宣言(6.7

6.2.6.2

整数型  unsigned char 以外の符号無し整数型において,オブジェクト表現のビットは値ビッ

ト及び詰め物ビットの二つのグループに分けられなければならない(詰め物ビットは存在しなくてもよ

い。

N

個の値ビットがある場合,それぞれのビットは 1 から 2

N

−1

までの,異なる 2 のべきを表現しなけ

ればならない。その結果,この型のオブジェクトは,純粋 2 進表現を用いて,0 から 2

N

1

までの値を表現

できなければならない。この表現方法を,値表現と呼ぶ。詰め物ビットの値はすべて未規定とする(

44

)

符号付き整数型において,オブジェクト表現のビットは,値ビット,詰め物ビット,及び符号ビットの

三つのグループに分けられなければならない。詰め物ビットは存在しなくてもよく,符号ビットはちょう

ど一つでなければならない。それぞれの値ビットは,対応する符号無し整数型のオブジェクト表現におけ

る同じビットと同じ値をもたなければならない。

(符号付き整数型に

M

個の値ビットがあり,符号無し整

数型に

N

個の値ビットがあれば,

M

N

)符号ビットが 0 であれば,それは結果の値に影響を及ぼしては

ならない。符号ビットが 1 であれば,値は次に示す方法の一つに従って変更されなければならない。

−  符号ビットが 0 のときの値を負数化した値[

符号と絶対値(sign and magnitude)]

−  符号ビットが値

 (2

N

)

をもつとするときの値[2

の補数(two's complement)]

−  符号ビットが値

 (2

N

1)

をもつとするときの値[1

の補数(one's complement)]

これらのうちいずれが適用されるかは処理系定義とする。同様に,符号ビットが 1 ですべての値ビットが

0

である数(符号と絶対値若しくは 2 の補数の場合)

,又は符号ビット及びすべての値ビットが 1 である値

(1 の補数の場合)が,トラップ表現であるか又は通常の値であるかも処理系定義とする。符号と絶対値

───────────────────────────────────────────────

(43)

同じ有効型 T をもつオブジェクト x と y が,T 型のオブジェクトとしてアクセスされる場合に同じ

値をもち,他の文脈では異なる値をもつことがありうる。特に T 型に対して==演算が定義されてい

るとしても,x == y は memcmp(&x, &y, sizeof(T)) == 0 であることを意味しない。さら

に,x == y は x と y が同じ値をもつことを必ずしも意味しない。T 型の値に対する他の演算では

結果が違うかもしれない。

(44)

詰め物ビットの幾つかの組合せが,トラップ表現を生む可能性がある。例として,詰め物ビットの

一つがパリティビットの場合がある。それにもかかわらず,オーバフローのように例外条件の一部

となる場合(符号無し型では起こり得ない)を除き,正しい値を用いる算術演算が,トラップ表現

を生成することはない。詰め物ビットのその他の組合せは,値ビットによって指定された値の代替

的なオブジェクト表現となる。


30

X 3010

:2003 (ISO/IEC 9899:1999)

     

の場合,又は 1 の補数の場合,この表現が通常の値であるならば,これを

負の 0(negative zero)と呼ぶ。

処理系が負の 0 をサポートする場合,処理系が負の 0 を生成するのは次に示す演算の場合に限られなけ

ればならない。

−  負の 0 を生成するオペランドを伴った,&,|,^,~,<<,及び>>演算子

−  一方のオペランドが負の 0 で,結果が 0 となる,+,-,*,/,及び%演算子

−  上に掲げた二つの場合に基づく複合代入演算子

これらの場合に実際に負の 0 を生成するか,又は通常の 0 を生成するかは未規定とする。また,負の 0 が,

オブジェクトに格納されるときに通常の 0 になるかどうかも未規定とする。

処理系が負の 0 をサポートしない場合,負の 0 を生成するオペランドを伴った&,|,^,~,<<,及び

>>

演算の結果は未定義とする。

詰め物ビットの値は未規定とする(

45

)

。符号ビットが 0 である符号付き整数型の正しい(例外でない)オ

ブジェクト表現は,対応する符号無し整数型の正しいオブジェクト表現で,これと同じ値を表現しなけれ

ばならない。

整数型の

精度(precision)とは,値を表現するのに用いられるビット(符号ビットと詰め物ビットは含

めない。

)の数とする。整数型の

幅(width)も同じとするが,符号ビットは含める。符号無し整数型では

これら二つは等しいが,符号付き整数型では幅は精度より 1 大きい。

6.2.7

適合型及び合成型  二つの型が同じ場合,二つの型は適合する(compatible)とする。これ以外に

二つの型が適合する場合を定める規則は,型指定子については 6.7.2 で,型修飾子については 6.7.3 で,宣

言子については 6.7.5 で規定する(

46

)

。さらに,別々の翻訳単位で宣言された二つの構造体型,共用体型又

は列挙型は,それらのタグ及びメンバが次に示す要求を満たす場合に,適合する。

−  一方がタグ付きで宣言されている場合,もう一方も同じタグ付きで宣言されていなければならない。

−  両方が完全型であれば,次に示す要求が新たに満たされなければならない。すなわち,両方のメンバ

の間に 1 対 1 の対応がつき,対応するメンバ同士が適合する型をもち,更に対応するメンバの一方が

名前付きで宣言されているならば,もう一方も同じ名前付きで宣言されていなければならない。

−  二つの構造体については,対応するメンバは同じ順序で宣言されていなければならない。

−  二つの構造体又は共用体については,対応するビットフィールドは同じ幅をもたなければならない。

−  二つの列挙体については,対応するメンバは同じ値をもたなければならない。

同じオブジェクト又は関数を参照するすべての宣言は,適合する型をもたなければならない。そうでなけ

れば,その動作は未定義とする。

合成型(composite type)は,適合する二つの型から構成することができる。合成型は,二つの型の両方

に適合し,かつ次の条件を満たす型とする。

−  一方の型が既知の固定長をもつ配列の場合,合成型は,その大きさの配列とする。そうでなく,一方

の型が可変長の配列の場合,合成型はその型とする。

───────────────────────────────────────────────

(45)

詰め物ビットの幾つかの組合せが,トラップ表現を生む可能性がある。例として,詰め物ビットの

一つがパリティビットの場合がある。それにもかかわらず,オーバフローのように例外条件の一部

となる場合を除き,正しい値を用いる算術演算が,トラップ表現を生成することはない。詰め物ビ

ットのその他の組合せは,値ビットによって指定された値の代替的なオブジェクト表現となる。

(46)

二つの型が適合するためには,完全に同じである必要はない。


31

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  一方の型だけが仮引数型並びをもつ関数型(関数原型)の場合,合成型は,その仮引数型並びをもつ

関数原型とする。

−  両方の型が仮引数型並びをもつ関数型の場合,合成仮引数型並びにおける各仮引数の型は,対応する

仮引数の型の合成型とする。

これらの規則は,二つの型が派生される元の型に再帰的に適用する。

内部結合又は外部結合をもつ識別子が,ある有効範囲の中で宣言され,その識別子の以前の宣言が可視

であり(

47

)

,以前の宣言が内部結合又は外部結合を指定している場合,現在の宣言での識別子の型は合成型

となる。

例  次の二つのファイル有効範囲をもつ宣言が与えられた場合,

int f(int (*)(), double (*)[3]);

int f(int (*)(char *), double (*)[]);

得られる関数の合成型は,

int f(int (*)(char *), double (*)[3]);

である。

6.3

型変換  幾つかの演算子は,オペランドの値をある型から他の型へ自動的に型変換する。6.3 は,こ

暗黙の型変換(implicit conversion)の結果及びキャスト演算[明示的な型変換(explicit conversion)]の

結果に対する要求を規定する。通常の演算子によって行われるほとんどの型変換は,6.3.1.8 にまとめる。

各演算子における型変換については,必要に応じて 6.5 に補足する。

適合する型へのオペランドの値の型変換は,値又は表現の変更を引き起こさない。

前方参照  キャスト演算子(6.5.4

6.3.1

算術オペランド

6.3.1.1

論理型,文字型及び整数型  すべての整数型は,次のとおり定義される整数変換の順位(integer

conversion rank

)をもつ。

−  二つの符号付き整数型は,同じ表現をもつ場合であっても,同じ順位をもってはならない。

−  符号付き整数型は,より小さい精度の符号付き整数型より高い順位をもたなければならない。

−  long long int 型は long int 型より高い順位をもたなければならない。long int 型は int 型

より高い順位をもたなければならない。int 型は short int 型より高い順位をもたなければならな

い。short int 型は signed char 型より高い順位をもたなければならない。

−  ある符号無し整数型に対し,対応する符号付き整数型があれば,両方の型は同じ順位をもたなければ

ならない。

−  標準整数型は,同じ幅の拡張整数型より高い順位をもたなければならない。

−  char 型は,signed char 型及び unsigned char 型と同じ順位をもたなければならない。

−  _Bool 型は,その他のすべての標準整数型より低い順位をもたなければならない。

−  すべての列挙型は,それぞれと適合する整数型と同じ順位をもたなければならない(6.7.2.2 参照)

−  精度の等しい拡張符号付き整数型同士の順位は処理系定義とするが,整数変換の順位を定める他の規

則に従わなければならない。

−  任意の整数型 T1,T2,及び T3 について,T1 が T2 より高い順位をもち,かつ T2 が T3 より高い順

───────────────────────────────────────────────

(47)

新しい宣言は以前の宣言を隠すことがある(6.2.1 参照)


32

X 3010

:2003 (ISO/IEC 9899:1999)

     

位をもつならば,T1 は T3 より高い順位をもたなければならない。

int

型又は unsigned int 型を使用してよい式の中ではどこでも,次に示すものを使用することがで

きる。

−  整数変換の順位が int 型及び unsigned int 型より低い整数型をもつオブジェクト又は式

−  _Bool 型,int 型,signed int 型,又は unsigned int 型のビットフィールド

これらのものの元の型のすべての値を int 型で表現可能な場合,その値を int 型に変換する。そうでな

い場合,unsigned int 型に変換する。これらの処理を,

整数拡張(integer promotion)と呼ぶ(

48

)

。これ

ら以外の型が整数拡張によって変わることはない。

整数拡張は,符号を含めてその値を変えない。

“単なる”char 型を符号付きとして扱うか否かは,処理

系定義とする(6.2.5 参照)

前方参照  構造体指定子及び共用体指定子(6.7.2.1),列挙型指定子(6.7.2.2

6.3.1.2

論理型  任意のスカラ値を_Bool 型に変換する場合,その値が 0 に等しい場合は結果は 0 とし,

それ以外の場合は 1 とする。

6.3.1.3

符号付き整数型及び符号無し整数型  整数型の値を_Bool 型以外の他の整数型に変換する場合,

その値が新しい型で表現可能なとき,値は変化しない。

新しい型で表現できない場合,新しい型が符号無し整数型であれば,新しい型で表現しうる最大の数に

1

加えた数を加えること又は減じることを,新しい型の範囲に入るまで繰り返すことによって得られる値

に変換する(

49

)

そうでない場合,すなわち,新しい型が符号付き整数型であって,値がその型で表現できない場合は,

結果が処理系定義の値となるか,又は処理系定義のシグナルを生成するかのいずれかとする。

6.3.1.4

実浮動小数点型及び整数型  実浮動小数点型の有限の値を_Bool 型以外の整数型に型変換する

場合,小数部を捨てる(すなわち,値を 0 方向に切り捨てる。

。整数部の値が整数型で表現できない場合,

その動作は未定義とする(

50

)

整数型の値を実浮動小数点型に型変換する場合,変換する値が新しい型で正確に表現できるとき,その

値は変わらない。変換する値が表現しうる値の範囲内にあるが正確に表現できないならば,その値より大

きく最も近い表現可能な値,又はその値より小さく最も近い表現可能な値のいずれかを処理系定義の方法

で選ぶ。変換する値が表現しうる値の範囲外にある場合,その動作は未定義とする。

6.3.1.5

実浮動小数点型  float を double 若しくは long double に拡張する場合,又は double を

long double

に拡張する場合,その値は変化しない。

double

を float に変換する場合,long double を double 若しくは float に変換する場合,又

───────────────────────────────────────────────

(48)

整数拡張は,通常の算術型変換の一部として,実引数を表す式に,単項の+,-,及び~演算子のオ

ペランドに,又はシフト演算子の両オペランドにだけ適用される。それぞれについて記述している

箇条の規定に従って適用する。

(49)

この規則は数学的な値に関する計算についての規則であり,式の与えられた型の値についての規則

ではない。

(50)

実浮動小数点型の値を符号無し整数型に型変換する場合,整数型の値を符号無し整数型に型変換す

るときに行われる剰余操作が行われるとは限らない。したがって,

可搬な実浮動小数点値の範囲は,

1

,U

type

_MAX

+1

)である。


33

X 3010

:2003 (ISO/IEC 9899:1999)

     

は,意味上の型(6.3.1.8 参照)が要求するより高い精度及び広い範囲で表現された値をその意味上の型に

明示的に変換する場合,変換する値がその新しい型で正確に表現できるならば,その値は変わらない。変

換する値が,表現しうる値の範囲内にあるが正確に表現できない場合,その結果は,その値より大きく最

も近い表現可能な値,

又はその値より小さく最も近い表現可能な値のいずれかを処理系定義の方法で選ぶ。

変換する値が表現しうる値の範囲外にある場合,その動作は未定義とする。

6.3.1.6

複素数型  複素数型の値を他の複素数型に変換する場合,実部と虚部の両方に,対応する実数型

の変換規則を適用する。

6.3.1.7

実数型及び複素数型  実数型の値を複素数型に変換する場合,複素数型の結果の実部は対応する

実数型への変換規則により決定し,複素数型の結果の虚部は正の 0 又は符号無しの 0 とする。

複素数型の値を実数型に変換する場合,複素数型の値の虚部を捨て,実部の値を,対応する実数型の変

換規則に基づいて変換する。

6.3.1.8

通常の算術型変換  算術型のオペランドをもつ多くの演算子は,同じ方法でオペランドの型変換

を行い,結果の型を決める。型変換は,オペランドと結果の

共通の実数型(common real type)を決めるた

めに行う。与えられたオペランドに対し,それぞれのオペランドは,型領域を変えることなく,共通の実

数型を対応する実数型とする型に変換する。この規格で明示的に異なる規定を行わない限り,結果の対応

する実数型も,この共通の実数型とし,その型領域は,オペランドの型領域が一致していればその型領域

とし,一致していなければ複素数型とする。これを

通常の算術型変換(usual arithmetic conversion)と呼ぶ。

通常の算術型変換の規則は,次による。

まず,一方のオペランドの対応する実数型が long double ならば,他方のオペランドを,型領域を

変えることなく,変換後の型に対応する実数型が long double となるように型変換する。

そうでない場合,一方のオペランドの対応する実数型が double ならば,他方のオペランドを,型領

域を変えることなく,変換後の型に対応する実数型が double となるように型変換する(

51

)

そうでない場合,一方のオペランドの対応する実数型が float ならば,他方のオペランドを,型領域

を変えることなく,変換後の型に対応する実数型が float となるように型変換する。

そうでない場合,

整数拡張を両オペランドに対して行い,

拡張後のオペランドに次の規則を適用する。

−  両方のオペランドが同じ型をもつ場合,更なる型変換は行わない。

−  そうでない場合,両方のオペランドが符号付き整数型をもつ,又は両方のオペランドが符号無し整

数型をもつならば,整数変換順位の低い方の型を,高い方の型に変換する。

−  そうでない場合,符号無し整数型をもつオペランドが,他方のオペランドの整数変換順位より高い

又は等しい順位をもつならば,符号付き整数型をもつオペランドを,符号無し整数型をもつオペラ

ンドの型に変換する。

−  そうでない場合,符号付き整数型をもつオペランドの型が,符号無し整数型をもつオペランドの型

のすべての値を表現できるならば,符号無し整数型をもつオペランドを,符号付き整数型をもつオ

ペランドの型に変換する。

−  そうでない場合,両方のオペランドを,符号付き整数型をもつオペランドの型に対応する符号無し

整数型に変換する。

───────────────────────────────────────────────

(51)

例えば,double _Complex 型と float 型を加える場合,float 型オペランドを double 型に変

換しさえすればよい(結果は double _Complex 型になる。


34

X 3010

:2003 (ISO/IEC 9899:1999)

     

浮動小数点型のオペランドの値及び式の結果の値を,

型が要求する精度や範囲を超えて表現してもよい。

ただし,それによって型が変わることはない(

52

)

6.3.2

他のオペランド

6.3.2.1

左辺値,配列及び関数指示子  左辺値(lvalue)は,オブジェクト型,又は void 以外の不完全型

をもつ式とする(

53

)

。左辺値が評価されたときにオブジェクトを指し示していなければ,動作は未定義とす

る。オブジェクトがもつ型に言及する場合,その型とは,オブジェクトを指し示すために用いる左辺値に

よって指定される型とする。

変更可能な左辺値(modifiable lvalue)とは,配列型をもたず,不完全型をも

たず, const 修飾型をもたない左辺値とし,それが構造体又は共用体の場合,const 修飾型のメンバ(再帰

的に包含されているすべての集成体又は共用体の任意のメンバ又は要素を含めて)

をもたないものとする。

左辺値が sizeof 演算子,単項&演算子,++演算子若しくは--演算子のオペランド,又は,演算子若し

くは代入演算子の左側のオペランドである場合を除いて,配列型以外の左辺値は,指し示されたオブジェ

クトが格納する値に変換する(そして,それはもはや左辺値ではない。

。左辺値が修飾型をもつ場合,そ

の値は左辺値の型の非修飾版をもつ。そうでない場合,その値は左辺値の型をもつ。左辺値が不完全型を

もち,配列型以外の型をもつ場合,その動作は未定義とする。

左辺値が sizeof 演算子のオペランド,単項&演算子のオペランド,又は文字配列を初期化するのに使

われる文字列リテラルである場合を除いて,型“∼型の配列”をもつ式は,型“∼型へのポインタ”の式

に型変換する。それは配列オブジェクトの先頭の要素を指し,左辺値ではない。配列オブジェクトがレジ

スタ記憶域クラスをもつ場合,その動作は未定義とする。

関数指示子(function designator)は,関数型をもつ式とする。関数指示子が sizeof 演算子(

54

)

又は単項

&

演算子のオペランドである場合を除いて,型“∼型を返す関数”をもつ関数指示子は,型“∼型を返す

関数へのポインタ”をもつ式に変換する。

前方参照  sizeof 演算子(6.5.3.4),アドレス及び間接演算子(6.5.3.2),共通の定義<stddef.h>(7.17),

構造体及び共用体のメンバ(6.5.2.3

,後置増分及び後置減分演算子(6.5.2.4

,初期化(6.7.8

,前置増分

及び前置減分演算子(6.5.3.1

,代入演算子(6.5.16

6.3.2.2

void

ボイド式(void expression)(型 void をもつ式)の(存在しない)値は,いかなる方法で

も使ってはならない。ボイド式には,暗黙の型変換も明示的な型変換(void への型変換を除く。

)も適用

してはならない。他の型の式をボイド式として評価する場合,その値又は指示子は捨てる。

(ボイド式は,

副作用のために評価する。

───────────────────────────────────────────────

(52)

この場合でもキャストと代入演算子は,型変換を行うことを要求される(6.3.1.4 及び 6.3.1.5 で規定

する。

(53)

“左辺値”という名前は,代入式 E1=E2 から由来している。すなわち,代入式の左のオペランド

E1

は,

(変更可能な)左辺値となる必要がある。左辺値は,オブジェクトの位置を示す値を表現す

るものと考えたほうがよいかもしれない。時として“右辺値”と呼ばれるものは,この規格におい

ては“式の値”として記述する。

左辺値の最も明確な例は,オブジェクトの識別子である。もう一つの例としては,E がオブジェ

クトへのポインタである単項式ならば,*E は E が指すオブジェクトを指し示す左辺値である。

(54)

この型変換が起こらないから,sizeof 演算子のオペランドは,関数指示子のまま残り,6.5.3.4 

制約に違反することになる。


35

X 3010

:2003 (ISO/IEC 9899:1999)

     

6.3.2.3

ポインタ  void へのポインタは,任意の不完全型若しくはオブジェクト型へのポインタに,又

はポインタから,型変換してもよい。任意の不完全型又はオブジェクト型へのポインタを,void へのポ

インタに型変換して再び戻した場合,結果は元のポインタと比較して等しくなければならない。

任意の型修飾子

q

に対して非

q

修飾型へのポインタは,その型の

q

修飾版へのポインタに型変換しても

よい。元のポインタと変換されたポインタに格納された値は,比較して等しくなければならない。

値0をもつ整数定数式又はその定数式を型void *にキャストした式を,

空ポインタ定数(null pointer

constant

)(

55

)

と呼ぶ。空ポインタ定数をポインタ型に型変換した場合,その結果のポインタを

空ポインタ

(null pointer)と呼び,いかなるオブジェクト又は関数へのポインタと比較しても等しくないことを保証

する。

空ポインタを他のポインタ型に型変換すると,その型の空ポインタを生成する。二つの空ポインタは比

較して等しくなければならない。

整数は任意のポインタ型に型変換できる。これまでに規定されている場合を除き,結果は処理系定義と

し,正しく境界調整されていないかもしれず,被参照型の実体を指していないかもしれず,トラップ表現

であるかもしれない(

56

)

任意のポインタ型は整数型に型変換できる。これまでに規定されている場合を除き,結果は処理系定義

とする。結果が整数型で表現できなければ,その動作は未定義とする。結果は何らかの整数型の値の範囲

に含まれているとは限らない。

オブジェクト型又は不完全型へのポインタは,他のオブジェクト型又は不完全型へのポインタに型変換

できる。その結果のポインタが,被参照型に関して正しく境界調整されていなければ(

57

)

,その動作は未定

義とする。そうでない場合,再び型変換で元の型に戻すならば,その結果は元のポインタと比較して等し

くなければならない。オブジェクトへのポインタを文字型へのポインタに型変換する場合,その結果はオ

ブジェクトの最も低位のアドレスを指す。その結果をオブジェクトの大きさまで連続して増分すると,そ

のオブジェクトの残りのバイトへのポインタを順次生成できる。

ある型の関数へのポインタを,別の型の関数へのポインタに型変換することができる。さらに再び型変

換で元の型に戻すことができるが,その結果は元のポインタと比較して等しくなければならない。型変換

されたポインタを関数呼出しに用い,関数の型がポインタが指すものの型と適合しない場合,その動作は

未定義とする。

前方参照  オブジェクトを指すポインタを保持可能な整数型(7.18.1.4),キャスト演算子(6.5.4),単純代

入(6.5.16.1

,等価演算子(6.5.9

6.4

字句要素

構文規則

───────────────────────────────────────────────

(55)

空ポインタ定数としてマクロ NULL が<stddef.h>(及び他のヘッダ)で定義されている(7.17 

照)

(56)

ポインタを整数に変換する関数,又は整数をポインタに変換する関数は,実行環境におけるアドレ

ス構造に関して一貫した動作をするように作られている。

(57)

一般には,

“境界を正しく調整する”という概念は推移的である。すなわち,型 A のポインタが型 B

のポインタとして境界を正しく調整され,それが型 C のポインタとしても境界を正しく調整されて

いるならば,型 A のポインタは型 C のポインタとして境界を正しく調整されている。


36

X 3010

:2003 (ISO/IEC 9899:1999)

     

字句:

キーワード

識別子

定数

文字列リテラル

区切り子

前処理字句:

ヘッダ名

識別子

前処理数

文字定数

文字列リテラル

区切り子

上の分類のいずれにも当てはまらない非空白類文字

制約  字句に変換される各前処理字句は,キーワード,識別子,定数,文字列リテラル又は区切り子の字

句としての形式をもたなければならない。

意味規則  字句(token)は,翻訳フェーズ(7)及び(8)において言語の最小の字句的な単位とする。字

句の分類は,キーワード,識別子,定数,文字列リテラル及び区切り子とする。前処理字句は,翻訳フェ

ーズ(3)から(6)までにおいて言語の最小の字句的な単位とする。前処理字句の分類は,ヘッダ名,識

別子,前処理数,文字定数,文字列リテラル,区切り子,及び字句的に他の前処理字句の分類に一致しな

い単一の非空白類文字とする(

58

)

。文字'又は文字"がその最後の分類に入る場合,その動作は未定義とす

る。前処理字句は,間に

空白類(white space)を入れて分離することができる。空白類とは,注釈(6.4.9

で規定する。

空白類文字(white-space character)(空白,水平タブ,改行,垂直タブ及び書式送り),又

はその両方のこととする。翻訳フェーズ(4)のある状況下では空白類(又はそれが存在しないこと)は前

処理字句を区切る以外の役割を果たす(6.10 で規定する。

。  空白類が前処理字句の中に現れてよいのは,

ヘッダ名の一部又は文字定数若しくは文字列リテラルの引用符と引用符の間だけとする。

入力ストリームをある文字まで前処理字句に解析し終わったとき,次の前処理字句は,前処理字句を構

成することのできる最も長い文字の並びとする。この規則には一つの例外がある。すなわち,ヘッダ名前

処理字句は,#include 前処理指令の中だけで認識し,この指令の中では,ヘッダ名としても文字列リテ

ラルとしても解釈できる文字の並びは,ヘッダ名として認識する。

1.  プログラム片 1Ex は,(正しい浮動小数点定数字句でも整数定数字句でもない)一つの前処理

数字句として解釈する。これは,たとえ(例えば,Ex が+1 としてマクロ定義されていて)二

つの前処理字句 1 及び Ex に分ければ正しい式として解釈できる場合でも,同じである。同様

に,E がマクロ名であろうとなかろうと,プログラム片 1E1 は前処理数(正しい浮動小数点定

数字句)として解釈する。

───────────────────────────────────────────────

(58)

追加の分類であるプレースマーカは,翻訳フェーズ(4)の内部で使用される(6.10.3.3 参照)

。プレ

ースマーカは,ソースファイルに出現することはない。


37

X 3010

:2003 (ISO/IEC 9899:1999)

     

2.  プログラム片 x+++++y は,x ++ ++ + y として解釈する。これは増分演算子の制約に違反

するが,正しい式になりうる解釈 x ++ + ++ y は採らない。

前方参照  後置増分及び後置減分演算子(6.5.2.4),式(6.5),前置増分及び前置減分演算子(6.5.3.1),注

釈(6.4.9

,浮動小数点定数(6.4.4.2

,ヘッダ名(6.4.7

,前処理指令(6.10

,前処理数(6.4.8

,マクロ

置き換え(6.10.3

,文字定数(6.4.4.4

,文字列リテラル(6.4.5

6.4.1

キーワード

構文規則

キーワード:次のいずれか

auto enum restrict

unsigned

 break

extern

return

void

 case

float

short

volatile

 char

for

signed

while

 const

goto

sizeof

_Bool

 continue

if static

_Complex

 default

inline

struct

_Imaginary

 do int

switch

 double

long

typedef

 else

register

union

意味規則  上に掲げた字句(大文字小文字の違いには意味がある。)は,キーワードとして用いるために[翻

訳フェーズ(7)及び(8)で]予約しており,その他の目的に使用してはならない。

6.4.2

識別子

6.4.2.1

一般的規定

構文規則

識別子:

識別子用非数字

識別子  識別子用非数字

識別子  数字

識別子用非数字:

非数字

国際文字名

その他の処理系定義の文字

非数字:次のいずれか

               _  a  b  c  d  e  f  g  h  i  j  k  l  m

n  o  p  q  r  s  t  u  v  w  x  y  z

A  B  C  D  E  F  G  H  I  J  K  L  M

N  O  P  Q  R  S  T  U  V  W  X  Y  Z

数字:次のいずれか

0  1  2  3  4  5  6  7  8  9


38

X 3010

:2003 (ISO/IEC 9899:1999)

     

意味規則  識別子は,非数字文字(下線_,小文字及び大文字のラテン英字,並びにその他の文字を含む)

及び数字の列とする。識別子は,一つ又はそれ以上の実体を指し示す(6.2.1 参照)

。英小文字と英大文字

は,区別する。識別子の最大の長さに,特別の制限はない。

識別子の中のそれぞれの国際文字名が指定する文字は,その ISO/IEC 10646 での表現形式が

附属書 

示す範囲の一つに分類されるものでなければならない(

59

)

。先頭の文字は,数字を表す国際文字名であって

はならない。処理系は,ソース基本文字集合の一部でない多バイト文字が識別子の中に現れることを許し

てもよい。使用してよい多バイト文字及びその文字と国際文字名との対応は,処理系定義とする。

前処理字句を翻訳フェーズ(7)で字句に変換するとき,前処理字句をキーワードにも識別子にも変換で

きるならば,キーワードに変換する。

処理系限界  処理系は,意味がある先頭の文字の個数を制限してもよい(5.2.4.1 参照)。外部名(external

name

(外部結合をもつ識別子)は,

内部名(internal name)(マクロ名又は外部結合をもたない識別子)

より制限を強くしてもよい。識別子の意味がある文字の個数は,処理系定義とする。

意味がある文字が異なる識別子は,異なる識別子とする。二つの識別子が意味のない文字でだけ異なる

場合,その動作は未定義とする。

前方参照  国際文字名(6.4.3),マクロ置き換え(6.10.3

6.4.2.2

あらかじめ定義された識別子

意味規則  識別子_ _func_ _は,翻訳プログラムによって,それぞれの関数定義の左波括弧の直後に,次

の宣言が現れた場合と同じ規則で暗黙に宣言される。

                static const char _ _func_ _ [] = "

関数名";

関数名は,字句的に囲んでいる関数の名前とする(

60

)

この名前は,暗黙の宣言をソース文字集合で書き,そして次に翻訳フェーズ(5)で示したとおり実行文

字集合に変換した場合と同じ規則で符号化する。

例  次のプログラム片を考える。

#include <stdio.h>

  void

myfunc(void)

  {

   printf("%s

\n", _ _func_ _);

   /*

... */

  }

関数が呼び出されるたびに,次の名前を標準出力ストリームに表示する。

  myfunc

前方参照  関数定義(6.9.1

───────────────────────────────────────────────

(59)

リンカが拡張文字を受け付けることができないシステムでは,有効な外部識別子を形成するために,

国際文字名の表現形式を使用してもよい。例えば,他の目的では使われていない文字又は文字の並

びを,国際文字名の\u を符号化するために使用してもよい。拡張文字は,長い外部識別子を生成し

てもよい。

(60)

名前_ _func_ _は,どのような目的のためにも処理系によって予約されている(7.1.3)ため,名前

_

 _func_ _

を使用して他の識別子を宣言する場合,その動作は未定義になる。


39

X 3010

:2003 (ISO/IEC 9899:1999)

     

6.4.3

国際文字名

構文規則

        国際文字名:

                \u 16 進 4 数字

                \U 16 進 4 数字 16 進 4 数字

        16 進 4 数字:

                16 進数字 16 進数字 16 進数字 16 進数字

制約  国際文字名は,次に示す短い識別子をもつ文字を指定してはならない(

61

)

− 00A0 未満[0024($)

,0040(@)及び 0060(`)を除く。

− D800∼DFFF

補足説明  国際文字名は,基本文字集合の中にない文字を表すために識別子,文字定数及び文字列リテラ

ルの中で使用してもよい。

意味規則  国際文字名\U

nnnnnnnn

は,8 けたの短い識別子(ISO/IEC 10646 で規定)が

nnnnnnnn

である文

字を表す(

62

)

。同様に,国際文字名\u

nnnn

は,4 けたの短い識別子が

nnnn

である文字を表す(この文字の

8

けたの短い識別子は,0000

nnnn

である。

6.4.4

定数

構文規則

定数:

整数定数

浮動小数点定数

列挙定数

文字定数

制約  定数の値は,その型で表現可能な値の範囲の中になければならない。

意味規則  各定数は型をもつ。その型は定数の形式及び値から決まる。型の定め方は,後に詳述する。

6.4.4.1

整数定数

構文規則

整数定数:

                                10

進定数  整数接尾語

opt

                                8

進定数  整数接尾語

opt

                                16

進定数  整数接尾語

opt

                10

進定数:

非 0 数字

                                10

進定数  数字

                8

進定数:

───────────────────────────────────────────────

(61)

許されない文字は,基本文字集合の文字,並びに制御文字,文字 DELETE,及び S 領域(UTF-16

で使用するために予約されている。

)のために ISO/IEC 10646 で予約した符号位置である。

(62)

文字のための短い識別子は,ISO/IEC 10646-1/AMD9:1997 で最初に規定された。


40

X 3010

:2003 (ISO/IEC 9899:1999)

     

                               0

                                8

進定数  8 進数字

                16

進定数:

                                16

進接頭語 16 進数字

                                16

進定数 16 進数字

                16

進接頭語:  次のいずれか

                                0x  0X

非 0 数字:  次のいずれか

                                1  2  3  4  5  6  7  8  9

                8

進数字:  次のいずれか

                                0  1  2  3  4  5  6  7

                16

進数字:  次のいずれか

                                0  1  2  3  4  5  6  7  8  9

                a  b  c  d  e  f

                A  B  C  D  E  F

整数接尾語:

                                U

接尾語  L 接尾語

opt

                                U

接尾語 LL 接尾語

                                L

接尾語  U 接尾語

opt

                                LL

接尾語  U 接尾語

opt

                U

接尾語:  次のいずれか

                                u  U

                L

接尾語:  次のいずれか

                                l  L

                LL

接尾語:  次のいずれか

                                ll  LL

補足説明  整数定数は,数字で始まり,ピリオドも指数部ももたない。その定数の基数を指定する接頭語,

及び型を指定する接尾語をもってもよい。

10

進定数は,0 以外の数字から始まる 10 進数字列から成る。8 進定数は,0 で始まる 0 から 7 までの数

字だけの列から成る。16 進定数は,接頭語 0x 又は 0X をもち,その後ろに 10 進数字及び 10 から 15 まで

の値をそれぞれもつ a(又は A)から f(又は F)までの英字の列から成る。

意味規則  10 進定数は基数 10,8 進定数は基数 8,16 進定数は基数 16 で値を計算する。字句的に先頭の

数字が最も重みが大きい。

整数定数の型は,次の表の対応する並びの中で,その値を表現できる最初の型とする。


41

X 3010

:2003 (ISO/IEC 9899:1999)

     

接尾語 10 進定数

8

進定数又は 16 進定数

なし

int

long int

long long int

int

unsigned int

long int

unsigned long int

long long int

unsigned long long int

u

又は U

unsigned int

unsigned long int

unsigned long long int

unsigned int

unsigned long int

unsigned long long int

l

又は L

long int

long long int

long int

unsigned long int

long long int

unsigned long long int

u

又は U 及び l 又は L の両方

unsigned long int

unsigned long long int

unsigned long int

unsigned long long int

ll

又は LL

long long int

long long int

unsigned long long int

u

又は U 及び ll 又は LL の両方

unsigned long long int

unsigned long long int

整数定数がその並びの中のどの型でも表現できず,かつ拡張整数型がその値を表現できるとき,それは,

拡張整数型をもってもよい。該当する並びの中のすべての型が符号付きである場合,拡張整数型は符号付

きとする。その並びの中のすべての型が符号無しである場合,拡張整数型は符号無しとする。その並びが

符号付きと符号無しの両方の型を含む場合,拡張整数型は符号付きでも符号無しでもよい。

6.4.4.2

浮動小数点定数

構文規則

浮動小数点定数:

                                10

進浮動小数点定数

                                16

進浮動小数点定数

                10

進浮動小数点定数:

小数点定数  指数部

opt

浮動小数点接尾語

opt

数字列  指数部  浮動小数点接尾語

opt

                16

進浮動小数点定数:

                                16

進接頭語 16 進小数点定数  2 進指数部  浮動小数点接尾語

opt

                                16

進接頭語 16 進数字列  2 進指数部  浮動小数点接尾語

opt

小数点定数:

数字列

opt

 .

数字列

数字列  .

指数部:

                                e

符号

opt

数字列

                                E

符号

opt

数字列

符号:  次のいずれか

                                +  -

数字列:


42

X 3010

:2003 (ISO/IEC 9899:1999)

     

数字

数字列  数字

                16

進小数点定数:

                                16

進数字列

opt

 . 16

進数字列

                                16

進数字列  .

                2

進指数部:

                                p

符号

opt

数字列

                                P

符号

opt

数字列

                16

進数字列:

                                16

進数字

                                16

進数字列 16 進数字

浮動小数点接尾語:  次のいずれか

                                f  l  F  L

補足説明  浮動小数点定数は有効数字部(significand part)をもち,その後ろに指数部(exponent part)及

びその型を指定する接尾語が続いてもよい。有効数字部は,整数部を表す数字列,その後ろに続くピリオ

ド(.)

,更にその後ろに続く数字列(小数部を表す)から成る。指数部は,e,  E,  p 又は P の後ろに省

略可能な符号が付いた数字列から成る指数が続く。整数部又は小数部のいずれかがなければならない。10

進浮動小数点定数の場合,ピリオド又は指数部のいずれかがなければならない。

意味規則  有効数字部は,(10 進又は 16 進の)有理数として解釈する。指数部の数字列は,10 進整数とし

て解釈する。10 進浮動小数点定数の場合,指数は有効数字部に乗じる 10 のべき乗を示す。16 進浮動小数

点定数の場合,

指数は有効数字部に乗じる 2 のべき乗を示す。

10

進浮動小数点定数の場合,

又は FLT_RADIX

が 2 のべき乗でないときの 16 進浮動小数点定数の場合,その結果は,最も近い表現可能な値とするか,又

は,最も近い表現可能な値のすぐ隣(大きい値若しくは小さい値)で表現可能な値とするか,いずれかを

処理系定義の方法で選ぶ。FLT_RADIX が 2 のべき乗であるときの 16 進浮動小数点定数の場合,その結果

は,正確に丸めた値とする。

接尾語のない浮動小数点定数は,型 double をもつ。英字 f 又は F を接尾語としてもつ場合,型 float

をもつ。l 又は L を接尾語としてもつ場合,型 long double をもつ。

浮動小数点定数は,翻訳時と同じ規則に従って,内部形式に変換する。浮動小数点定数の変換は,実行

時に例外条件又は浮動小数点例外を生成してはならない。

推奨実装仕様  処理系は,16 進定数が評価形式で正確に表現できない場合,診断メッセージを出力するこ

とが望ましい。処理系は,それからプログラムの翻訳を続けることが望ましい。

浮動小数点定数の翻訳時変換は,次の条件を満たすライブラリ関数(例えば,strtod など)での文字

列の実行時変換と一致することが望ましい(

63

)

−  入力が両方の変換に適している。

−  同じ結果形式をもつ。

───────────────────────────────────────────────

(63)

ライブラリ関数の規定は,浮動小数点定数に要求されるよりも,更に正確な型変換を推奨する

7.20.1.3 参照)


43

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  既定の実行時丸めを行う。

6.4.4.3

【列挙定数】

構文規則

列挙定数:

識別子

意味規則  列挙定数として宣言された識別子は,型 int をもつ。

前方参照  列挙型指定子(6.7.2.2

6.4.4.4

文字定数

構文規則

文字定数:

                                ' c

文字列  '

                                L' c

文字列  '

                c

文字列:

                                c

文字

                                c

文字列  c文字

                c

文字:

一重引用符',逆斜線\及び改行文字を除くソース文字集合中の任意の要素

逆斜線表記

逆斜線表記:

単純逆斜線表記

                                8

進逆斜線表記

                                16

進逆斜線表記

国際文字名

単純逆斜線表記:  次のいずれか

\'    \"    \?    \\

\a    \b    \f    \n    \r    \t    \v

                8

進逆斜線表記:

\  8

進数字

\  8

進数字  8 進数字

\  8

進数字  8 進数字  8 進数字

                16

進逆斜線表記:

\x 16

進数字

                                16

進逆斜線表記 16 進数字

補足説明  単純文字定数は,一重引用符で囲まれた一つ以上の多バイト文字の並びとする(例えば'x')。

ワイド文字定数は,英字 L という接頭語が付いていることを除いて単純文字定数と同一とする。後に詳述

する幾つかの例外を除いて,列の要素はソース文字集合の任意の要素とする。それらは実行文字集合の要

素に処理系定義の方法で対応付ける。

一重引用符',二重引用符",疑問符?,逆斜線\及び任意の整数値は,次の逆斜線表記によって表現可能


44

X 3010

:2003 (ISO/IEC 9899:1999)

     

とする。

一重引用符  '

\'

二重引用符  "

\"

疑問符  ?

\?

逆斜線  \

\\

8

進整数

\8

進数字の列

 16

進整数

\x16

進数字の列

二重引用符"及び疑問符?は,それ自身ででも逆斜線表記\",\?ででも表現可能とするが,一重引用符'

及び逆斜線\はそれぞれ逆斜線表記\'及び逆斜線表記\\で表現しなければならない。

8

進逆斜線表記の中の逆斜線に続く 8 進数字の列は,単純文字定数に対する単一の文字,又はワイド文

字定数に対する単一のワイド文字を構成する役割を果たす。8 進整数の数値が,その文字又はワイド文字

の値を規定する。

16

進逆斜線表記の中の逆斜線及び英字 x に続く 16 進数字の列は,単純文字定数に対する単一の文字,

又はワイド文字定数に対する単一のワイド文字を構成する役割を果たす。16 進整数の数値が,その文字又

はワイド文字の値を規定する。

8

進逆斜線表記又は 16 進逆斜線表記は,逆斜線表記を構成できる最も長い文字の並びとする。

さらに,基本文字集合にない文字は,国際文字名によって表現可能とする。そして,特定の非図形文字

は,逆斜線\及びそれに続く英小文字で構成する逆斜線表記\a,\b,\f,\n,\r,\t 及び\v によって表

現可能とする(

64

)

制約  8 進逆斜線表記又は 16 進逆斜線表記の値は,単純文字定数に対しては unsigned char 型,ワイ

ド文字定数に対しては wchar_t 型に対応する符号無し整数型で表現可能な値の範囲内になければならな

い。

意味規則  単純文字定数は,型 int をもつ。1 バイトの実行文字に対応する単一の文字を含む単純文字定

数の値は,対応付けた文字の表現を整数として解釈した数値とする。2 文字以上を含む(例えば'ab')又

は 1 バイトの実行文字で表現できない文字若しくは逆斜線表記を含む単純文字定数の値は,処理系定義と

する。単純文字定数が単一の文字又は逆斜線表記を含む場合,その値はその単一の文字又は逆斜線表記の

値をもつ char 型のオブジェクトを int 型に変換したときの結果の値とする。

ワイド文字定数は,型 wchar_t(ヘッダ<stddef.h>の中で定義される整数型)をもつ。実行拡張文字

集合の一つの文字に対応する単一の多バイト文字を含むワイド文字定数の値は,その多バイト文字に対応

するワイド文字とする。その対応は,処理系定義のその時点のロケールにおける mbtowc 関数によって定

義する。2 文字以上の多バイト文字を含む又は実行拡張文字集合で表現できない多バイト文字若しくは逆

斜線表記を含むワイド文字定数の値は,処理系定義とする。

1.  普通,ナル文字を表すために表現'\0'を使う。

2.  整数に対し 2 の補数表現を用い,型 char をもつオブジェクトに対して 8 ビットを用いる処理

系を考える。型 char が signed char と同じ範囲の値をもつ処理系では,単純文字定数

'

\xFF'

は値

1

をもつ。型 char が unsigned char と同じ範囲の値をもつ場合,文字定数

───────────────────────────────────────────────

(64)

これらの文字の意味は,5.2.2 で規定している。他の文字が逆斜線の後に続く場合,その結果は字句

ではなく,診断メッセージの出力を必要とする。

“今後の言語の方針”

6.11.4)参照。


45

X 3010

:2003 (ISO/IEC 9899:1999)

     

'

\xFF'

は値+255 をもつ。

3.  たとえ,型 char をもつオブジェクトに対して 8 ビットを用いる場合でも,16 進逆斜線表記は

非 16 進文字によってだけ終了するので,表現'\x123'はただ 1 文字を含む単純文字定数を示

す。値が'\x12'及び値'3'である二つの文字を含む単純文字定数を指定するためには,8 進逆

斜線表記は三つの 8 進数字の後で終了するので,表現'\0223'を用いればよい。

(この二つの

文字から成る単純文字定数の値は,処理系定義である。

4.  たとえ,型 wchar_t をもつオブジェクトに対して 12 ビット以上を用いる場合でも,表現

L'

\1234'

は,値 0123 と値'4'の組合せから得られる処理系定義の値を指定する。

前方参照  mbtowc 関数(7.20.7.2),共通の定義<stddef.h>(7.17

6.4.5

文字列リテラル

構文規則

文字列リテラル:

                                " s

文字列

opt

 "

                                L" s

文字列

opt

 "

                s

文字列:

                                s

文字

                                s

文字列  s文字

                s

文字:

二重引用符",逆斜線\及び改行文字を除くソース文字集合中の任意の要素

逆斜線表記

補足説明  単純文字列リテラル(character string literal)は,二重引用符で囲まれた 0 個以上の多バイト文

字の並びとする(例えば"xyz"。

ワイド文字列リテラル(wide string literal)は,文字 L という接頭語を

もつことを除いて,単純文字列リテラルと同一とする。

文字列リテラル中では,一重引用符'はそれ自身ででも逆斜線表記\'ででも表現可能とするが,二重引

用符は逆斜線表記\"で表現しなければならない。このことを除けば,単純文字列リテラル又はワイド文字

列リテラル中の各要素に対して,その要素が単純文字定数又はワイド文字定数の中にあるとみなした場合

と同じ規則に従った考え方を適用する。

意味規則  翻訳フェーズ(6)において,隣り合う単純文字列リテラル字句又はワイド文字列リテラル字句

で指定される多バイト文字の並びは,連結して一つの多バイト文字の並びになる。字句のいずれかがワイ

ド文字列リテラルである場合,結果として生じる多バイト文字の並びは,ワイド文字列リテラルとして扱

う。それ以外の場合,それは単純文字列リテラルとして扱う。

翻訳フェーズ(7)において,文字列リテラル又はその並びから得られる多バイト文字の並びの最後に値

0

のバイト又はコードを付加する(

65

)

。結果の多バイト文字の並びは,静的記憶域期間をもち,かつその並

びを含むのにちょうど十分な長さの配列を初期化するのに用いる。単純文字列リテラルの場合,配列の要

素は型 char をもち,多バイト文字の並びの個々のバイトで初期化する。ワイド文字列リテラルの場合,

───────────────────────────────────────────────

(65)

一つの単純文字列リテラルが,一つの文字列(7.1.1 参照)になるとは限らない。なぜなら,ナル文

字を\0 逆斜線表記によってリテラルに埋め込んでもよいからである。


46

X 3010

:2003 (ISO/IEC 9899:1999)

     

配列の要素は型 wchar_t をもち,多バイト文字の並びに対応するワイド文字の並びで初期化する。その

対応は,処理系定義のその時点のロケールにおける mbstowcs 関数によって定義する。実行文字集合で表

現できない多バイト文字又は逆斜線表記を含む文字列リテラルの値は,処理系定義とする。

それらの要素が適切な値をもっている場合,これらの配列同士が別個であるかどうかは未規定とする。

プログラムがこれらの配列を変更しようとした場合,その動作は未定義とする。

例  隣り合った単純文字列リテラルの組

"

\x12"    "3"

は,隣り合う文字列リテラルの連結の前に逆斜線表記が実行文字集合の一つの要素に変換される

ので,値が'\x12'と値'3'の二つの文字を含む一つの単純文字列リテラルを作る。

前方参照  mbstowcs 関数(7.20.8.1),共通の定義<stddef.h>(7.17

6.4.6

区切り子

構文規則

区切り子:  次のいずれか

                                [  ]  (  )  {  }  .  ->

                ++  --  &  *  +  -  ~  !

                /  %  <<  >>  <  >  <=  >=  ==  !=  ^  |  &&  ||

                ?  :  ;  ...

                =  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=

                ,  #  ##

                <:  :>  <%  %>  %:  %:%:

意味規則  区切り子は,独立した構文的及び意味的な機能をもつ記号とする。文脈によっては,行うべき

操作(値又は関数指示子を生成する,副作用を引き起こす,又はそれらの組合せ)を指定することもある。

この場合,それを

演算子(operator)と呼ぶ(文脈によっては,これ以外の演算子が存在することもある。)。

オペランド(operand)は,演算子が作用する実体とする。

言語のすべての局面において,次の六つの字句は(

66

)

<:  :>  <%  %>  %:  %:%:

つづりが違うことだけを除いて(

67

)

,次の六つの字句とそれぞれ同じ動作をする。

[   ]   {   }   #   ##

前方参照  式(6.5),宣言(6.7),文(6.8),前処理指令(6.10

6.4.7

ヘッダ名

構文規則

ヘッダ名:

                                < h

文字列  >

                                " q

文字列  "

───────────────────────────────────────────────

(66)

これらの字句を,

“2 文字表記”と呼ぶ。

(67)

したがって,[及び<:は,

“文字列化”

6.10.3.2 参照)されるとき異なった動作をするが,  そうでな

ければ,  自由に置き換えることができる。


47

X 3010

:2003 (ISO/IEC 9899:1999)

     

                h

文字列:

                                h

文字

                                h

文字列  h文字

                h

文字:

改行文字及び>を除くソース文字集合中の任意の要素

                q

文字列:

                                q

文字

                                q

文字列  q文字

                q

文字:

改行文字及び"を除くソース文字集合中の任意の要素

意味規則  ヘッダ名の両方の形式中の文字列は,処理系定義の方法によってヘッダ又は外部ソースファイ

ルの名前に対応付ける(6.10.2 で規定)

文字',\,",//又は/*が区切り記号<と>の間の文字列中に現れた場合,その動作は未定義とする。同

様に,文字',\,//又は/*が二つの区切り記号"の間の文字列中に現れた場合,その動作は未定義とする

(

68

)

。ヘッダ名前処理字句は,#include 前処理指令の中でだけ認識される。

例  次の文字の並び

0x3<1/a.h>1e2

  #include

<1/a.h>

  #define

const.member@$

は,次のような前処理字句列を形成する(各前処理字句を

{

及び

}

によって区切って示す。

{

0x3

}{

<

}{

1

}{

/

}{

a

}{

.

}{

h

}{

>

}{

1e2

}

{

#

}{

include

}

{

<1/a.h>

}

{

#

}{

define

}

{

const

}{

.

}{

member

}{

@

}{

$

}

前方参照  ソースファイル取込み(6.10.2

6.4.8

前処理数

構文規則

前処理数:

数字

                                .

数字

前処理数  数字

前処理数  識別子用非数字

前処理数  e符号

前処理数  E符号

前処理数  p符号

前処理数  P符号

前処理数  .

───────────────────────────────────────────────

(68)

このように,逆斜線表記に似た文字の並びは,未定義の動作の原因となる。


48

X 3010

:2003 (ISO/IEC 9899:1999)

     

補足説明  前処理数は,省略可能な先行するピリオド(.)をもつ数字で始まる。その後ろに正しい識別

子用文字及び文字の並び e+,e-,E+,E-,p+,p-,P+又は P-が続いてもよい。

前処理数字句は,字句的にすべての浮動小数点定数字句及び整数定数字句を含む。

意味規則  前処理数は,型も値ももたない。型と値は,[翻訳フェーズ(7)で]浮動小数点定数字句又は

整数定数字句に変換された結果として決まる。

6.4.9

注釈  文字定数,文字列リテラル又は注釈の中を除いて,文字の並び/*は注釈の始まりを示す。

注釈の内容は,多バイト文字を識別すること及び注釈を終了させる文字の並び*/を捜すことだけのために

調べる(

69

)

文字定数,文字列リテラル又は注釈の中を除いて,文字の並び//は注釈の始まりを示す。この形式の注

釈は,次の改行文字までのすべての多バイト文字を含むが,改行文字自身は含まない。注釈の内容は,多

バイト文字を識別すること及び注釈を終了させる改行文字を捜すことだけのために調べる。

"a//b"

   //

4

文字の文字列リテラル

#include

"//e"  //

未定義の動作

//

*/

   //

構文エラーではなく,注釈

f = g/**//h;

// f = g / h;

と等しい

//

  i();

   //

2

行にまたがる注釈の部分

/

  /

j();

   //

2

行にまたがる注釈の部分

#define glue(x,y) x##y

  glue(/,/)

k();  //

注釈ではなく,構文エラー

/*//*/ l();

// l();

と等しい

m = n//**/o

  + p;

// m = n + p;

と等しい

6.5

式  式(expression)は,演算子及びオペランドの列とする。式は,値の計算を指定するか,オブジ

ェクト若しくは関数を指し示すか,副作用を引き起こすか,又はそれらの組合せを行う。

直前の副作用完了点から次の副作用完了点までの間に,式の評価によって一つのオブジェクトに格納さ

れた値を変更する回数は,高々1 回でなければならない。さらに,変更前の値の読取りは,格納される値

を決定するためだけに行われなければならない(

70

)

───────────────────────────────────────────────

(69)

したがって,注釈/* ... */の入れ子はない。

(70)

この段落の規定によると,

                i = i + 1;

        a[i]  =  i;

は許されるが,

                i = ++i + 1;

        a[i++]  =  i;

は,未定義の式文である。


49

X 3010

:2003 (ISO/IEC 9899:1999)

     

演算子とオペランドのグループ分けを 6.5.16.5.17 の構文規則で示す(

71

)

(関数呼出しの(),

&&

||

?:

及びコンマ演算子に対して)後で規定する場合を除いて,部分式の評価順序及び副作用が生じる順序は未

規定とする。

幾つかの演算子[総称して

ビット単位の演算子(bitwise operator)と呼ぶ単項演算子~並びに 2 項演算子

<<

,>>,&,^及び|]は,整数型のオペランドを必要とする。これらの演算子は,整数の内部表現に依存

した値を返すので,符号付き整数型に対して処理系定義又は未定義の側面をもつ。

式の評価中に

例外条件(exceptional condition)が発生した場合(すなわち,結果が数学的に定義できな

いか,又は結果の型で表現可能な値の範囲にない場合)

,その動作は未定義とする。

格納された値にアクセスするときのオブジェクトの

有効型(effective type)は,(もしあれば)そのオブ

ジェクトの宣言された型とする(

72

)

。宣言された型をもたないオブジェクトへ,文字型以外の型をもつ左辺

値を通じて値を格納した場合,左辺値の型をそのアクセス及び格納された値を変更しないそれ以降のアク

セスでのオブジェクトの有効型とする。宣言された型をもたないオブジェクトに,memcpy 関数若しくは

memmove

関数を用いて値をコピーするか,又は文字型の配列として値をコピーした場合,そのアクセス及

び値を変更しないそれ以降のアクセスでのオブジェクトの有効型は,値のコピー元となったオブジェクト

の有効型があれば,その型とする。宣言された型をもたないオブジェクトに対するその他のすべてのアク

セスでは,そのアクセスでの左辺値の型を有効型とする。

オブジェクトに格納された値に対するアクセスは,次のうちのいずれか一つの型をもつ左辺値によらな

ければならない(

73

)

−  オブジェクトの有効型と適合する型

−  オブジェクトの有効型と適合する型の修飾版

−  オブジェクトの有効型に対応する符号付き型又は符号無し型

−  オブジェクトの有効型の修飾版に対応する符号付き型又は符号無し型

−  メンバの中に上に列挙した型の一つを含む集成体型又は共用体型(再帰的に包含されている部分集成

体又は含まれる共用体のメンバを含む。

−  文字型

浮動小数点型の式は

短縮(contract)してもよい。すなわち,ハードウェアによる不可分な操作として評

───────────────────────────────────────────────

(71)

構文は,式の評価における演算子の優先順位を指定する。それは 6.5 の箇条の順序と同じであり,

最初の箇条が最も高い優先順位をもつ。したがって,例えば 2 項+演算子(6.5.6)のオペランドと

して許される式は,6.5.16.5.6 で定義された式である。例外は,オペランドとしてキャスト式(6.5.4

をもってよい単項演算子(6.5.3)及び次に示す対の演算子で囲まれたオペランドである。すなわち,

グループ分けの括弧()(6.5.1

,添字付けの角括弧[](6.5.2.1

,関数呼出しの括弧()(6.5.2.2)及

び条件演算子?:(6.5.15

各箇条の中では,演算子は同じ優先順位をもつ。左結合であるか右結合であるかは,各箇条で述

べる式の構文によって示す。

(72)

割付けオブジェクトは宣言された型をもたない。

(73)

この列挙は,オブジェクトに別名を付けてもよい状況と,付けてはならない状況を規定するための

ものである。


50

X 3010

:2003 (ISO/IEC 9899:1999)

     

価して,ソースコードの記述及び式の評価方法どおりなら生じるはずの丸め誤差を省いてもよい(

74

)

<math.h>

の FP_CONTRACT プラグマは,式の短縮を禁止する方法を提供する。FP_CONTRACT プラグマ

がない場合,式が短縮されるかどうか,及びそれをどのように短縮するかは処理系定義とする(

75

)

前方参照  FP_CONTRACT プラグマ(7.12.2),コピー関数(7.21.2

6.5.1

一次式

構文規則

一次式:

識別子

定数

文字列リテラル

                                (

式    )

意味規則  識別子がオブジェクト(この場合,識別子は左辺値となる。),又は関数(この場合,関数指示

子となる。

)を指し示すと宣言されている場合,識別子は一次式とする(

76

)

定数は,一次式とする。その型は,その形式と値によって決まる(6.4.4 で規定する。

文字列リテラルは,一次式とする。それは,6.4.5 の規則で決まる型をもつ左辺値とする。

括弧で囲まれた式は,一次式とする。その型及び値は,括弧の中の式のそれらと同じとする。括弧の中

の式が左辺値,関数指示子又はボイド式である場合,それは,それぞれ左辺値,関数指示子又はボイド式

とする。

前方参照  宣言(6.7

6.5.2

後置演算子

構文規則

後置式:

一次式

後置式    [    式    ]

後置式    (    実引数式並び

opt

    )

後置式    .    識別子

後置式    ->    識別子

後置式    ++

後置式    --

                                (

型名  ) {  初期化子並び  }

                                (

型名  ) {  初期化子並び  , }

───────────────────────────────────────────────

(74)

短縮式では浮動小数点例外の発生を省略してもよい。

(75)

これは複数の C の演算子を結合させた高速な計算機命令の使用を許可することを明確に意図してい

る。式の短縮は,予測可能性を損なうおそれがあり,計算結果の正確さを低下させるおそれすらあ

る。したがって,短縮式を処理系が使用するに当たっては,仕様をよく定義し,明確に文書化する

必要がある。

(76)

したがって,宣言されていない識別子は構文規則違反である。


51

X 3010

:2003 (ISO/IEC 9899:1999)

     

実引数式並び:

代入式

実引数式並び    ,  代入式

6.5.2.1

配列の添字付け

制約  式の一方は,型“オブジェクト型∼型へのポインタ”をもたなければならない。もう一方の式は,

整数型をもたなければならない。結果は,型“∼型”をもつ。

意味規則  角括弧[]に囲まれた式を後ろに伴う後置式は,配列オブジェクトの要素の添字による指定とす

る。添字演算子[]は,E1[E2]が(*((E1)+(E2)))と等価であると定義する。2 項+演算子に適用する型

変換の規則によって,E1 が配列オブジェクト(又は,配列オブジェクトの先頭要素へのポインタ)であり,

E2

が整数である場合,E1[E2]は E1 の E2 番目(0 から数える。

)の要素を指し示す。

連続した添字演算子は,多次元配列の要素を指し示す。E が次元

i

×

j

×...×

k

をもつ

n

次元配列(

n

≧2)

である場合,E(左辺値以外として用いた場合。

)は,次元

j

×...×

k

をもつ(

n

1

)次元配列へのポインタ

に型変換する。単項*演算子をこのポインタに明示的に適用するか,又は暗黙に添字付けの結果として適

用する場合,その結果は,指されている(

n

1

)次元配列となり,それ自身を左辺値以外として用いる場

合,ポインタに型変換する。このことから,配列は,行優先の順序(最後の添字が最も速く変わる。

)で格

納する。

例  次の宣言で定義された配列オブジェクトを考える。

int x[3][5];

ここで x は,int の 3×5 の配列である。より正確には,x は三つの要素オブジェクトの配列であ

り,その各要素は,五つの int の配列である。式 x[i]は(*((x)+(i)))と等価であり,x をま

ず五つの int の配列の最初の一つへのポインタに型変換する。次に i を,x の型に対応するよう

に調整する。このことは,概念的にはポインタが指すオブジェクト,すなわち五つの int オブジ

ェクトの配列の大きさを i に乗じることを伴っている。これらの結果を加えて,間接演算を適用

することによって,五つの int の配列を生じる。式 x[i][j]中で用いられると,その配列は先

頭の int へのポインタに型変換され,その結果,x[i][j]は int を生じる。

前方参照  アドレス及び間接演算子(6.5.3.2),加減演算子(6.5.6),配列宣言子(6.7.5.2

6.5.2.2

関数呼出し

制約  呼び出される関数を表す式(

77

)

は,void を返す関数へのポインタ型,又は配列型以外のオブジェク

ト型を返す関数へのポインタ型をもたなければならない。

呼び出される関数を表す式が関数原型を含む型をもつ場合,実引数の個数は,仮引数の個数と一致しな

ければならない。各実引数は,対応する仮引数の型の非修飾版をもつオブジェクトにその値を代入するこ

とのできる型をもたなければならない。

意味規則  コンマで区切られた式の並び(空であってもよい。)を囲む括弧()を後ろに伴う後置式は,関

数呼出しとする。後置式は呼び出される関数を表す。式の並びは,関数への実引数を指定する。

実引数は,任意のオブジェクト型の式でよい。関数呼出しの準備の段階で,実引数を評価し,各実引数

───────────────────────────────────────────────

(77)

たいてい,これは関数指示子である識別子を型変換した結果である。


52

X 3010

:2003 (ISO/IEC 9899:1999)

     

の値を対応する仮引数に代入する(

78

)

呼び出される関数を表す式が,オブジェクト型を返す関数へのポインタ型をもつ場合,関数呼出し式は

そのオブジェクト型と同じ型をもち,その値は 6.8.6.4 で規定するとおりに決まる。そうでない場合,関数

呼出しは型 void をもつ。関数呼出しの結果を変更しようとした場合,又は次の副作用完了点の後にアク

セスしようとした場合,その動作は未定義とする。

呼び出される関数を表す式が,関数原型を含まない型をもつ場合,各実引数に対して整数拡張を行い,

型 float をもつ実引数は型 double に拡張する。

この操作を

既定の実引数拡張(default argument promotion)

と呼ぶ。実引数の個数と仮引数の個数が等しくない場合,その動作は未定義とする。関数原型を含む型で

関数を定義し,かつ,関数原型が省略記号(, ...)で終わっている場合,又は拡張後の実引数の型が,

仮引数の型と適合しない場合,その動作は未定義とする。関数原型を含まない型で関数を定義し,かつ拡

張後の実引数の型が,拡張後の仮引数の型と適合しない場合,その動作は未定義とする。ただし,次の場

合は除く。

−  拡張された型の一方が符号付き整数型で,他方が対応する符号無し整数型であり,かつ値がいずれの

型でも表現可能な場合。

−  いずれの型も文字型又は void の修飾版又は非修飾版へのポインタである場合。

呼び出される関数を表す式が関数原型を含む型をもつ場合,実引数は代入と同じ規則で,対応する仮引

数の型に暗黙に変換する。このとき各仮引数の型は,宣言した型の非修飾版とする。関数原型宣言子にお

ける省略記号表記は,最後に宣言されている仮引数の直後から実引数の型変換を止める。残りの実引数に

対しては,既定の実引数拡張を行う。

これら以外の型変換は,暗黙には行わない。特に,実引数の個数及び型を関数原型宣言子を含まない関

数定義中の仮引数の個数及び型と比較することはない。

呼び出される関数を表す式によって指される式の型が関数が定義された型と適合しない場合,その動作

は,未定義とする。

関数指示子,実引数及び実引数内の部分式の評価順序は未規定とするが,実際に呼出しが行われる前に

副作用完了点がある。

直接にも,他の関数の連鎖を通じて間接的にも,再帰関数呼出しが許される。

例  次の関数呼出しにおいて

(*pf[f1()]) (f2(), f3() + f4())

関数 f1,f2,f3 及び f4 は,任意の順序で呼んでもよい。すべての副作用は,pf[f1()]が指

す関数が呼ばれる前に完了していなければならない。

前方参照  return 文(6.8.6.4),関数宣言子(関数原型を含む)(6.7.5.3),関数定義(6.9.1),単純代入

6.5.16.1

6.5.2.3

構造体及び共用体のメンバ

制約  .演算子の最初のオペランドは,構造体型又は共用体型の修飾版又は非修飾版をもたなければなら

───────────────────────────────────────────────

(78)

関数は,その仮引数の値を変更してもよいが,これらの変更が実引数の値に影響を与えることはで

きない。一方,オブジェクトへのポインタを渡すことは可能であり,関数はそれによって指される

オブジェクトの値を変更してもよい。配列型又は関数型をもつと宣言された仮引数は,ポインタ型

をもつように型調整される(6.9.1 で規定する。


53

X 3010

:2003 (ISO/IEC 9899:1999)

     

ず,2 番目のオペランドは,その型のメンバの名前でなければならない。

->

演算子の最初のオペランドは,型“構造体の修飾版若しくは非修飾版へのポインタ”

,又は型“共用

体の修飾版若しくは非修飾版へのポインタ”をもたなければならず,2 番目のオペランドは,指される型

のメンバの名前でなければならない。

意味規則  .演算子及び識別子を後ろに伴う後置式は,構造体又は共用体オブジェクトの一つのメンバを

指し示す。その値は,指定されたメンバの値とする。最初の式が左辺値の場合,その式は,左辺値とする。

最初の式が修飾型をもつ場合,結果の型は,指定されたメンバの型に同じ修飾を加えた型とする。

->

演算子及び識別子を後ろに伴う後置式は,構造体又は共用体オブジェクトの一つのメンバを指し示す。

その値は,最初の式が指すオブジェクトの指定されたメンバの値とする。その式は左辺値とする(

79

)

。最初

の式の型が修飾型へのポインタである場合,結果の型は,指定されたメンバの型に同じ修飾を加えた型と

する。

共用体の使用を簡単にするため,次の保証をする。すなわち,共用体が同一の先頭のメンバの並びをも

つ幾つかの構造体を含み,共用体オブジェクトがそれらの構造体のいずれか一つを保持している場合,そ

の共用体の完全型の宣言が可視である場所ならばどこでも,いずれの構造体の同一の先頭のメンバの並び

の部分を参照してもよい。先頭から一つ以上のメンバの並びに対して,対応するメンバが適合する型(か

つ,ビットフィールドに対しては,同じ幅)をもつ場合,二つの構造体は,

同一の先頭のメンバの並び

(common initial sequence)をもつという。

1.  f が構造体又は共用体を返す関数で,x がその構造体又は共用体のメンバである場合,f().x

は正しい後置式である。しかし,左辺値ではない。

2.  次のプログラム例では,

struct s { int i; const int ci; };

struct s s;

const struct s cs;

volatile struct s vs;

各々のメンバは次の型をもつ。

s.i int

 s.ci

const

int

 cs.i

const

int

 cs.ci

const

int

 vs.i

volatile

int

vs.ci  volatile const int

3.  次の例は,正しいプログラム片である。

union {

   struct

{

int    alltypes;

   }

n;

───────────────────────────────────────────────

(79)

&E

が正しいポインタ式(ここで,&は“∼のアドレス”演算子であり,そのオペランドへのポイン

タを生成する。

)の場合,式(&E)->MOS は,E.MOS と同じである。


54

X 3010

:2003 (ISO/IEC 9899:1999)

     

   struct

{

int    type;

int    intnode;

   }

ni;

   struct

{

int    type;

     double

doublenode;

   }

nf;

 }

u;

u.nf.type = 1;

u.nf.doublenode = 3.14;

 /*

... */

if (u.n.alltypes == 1)

if (sin(u.nf.doublenode) == 0.0)

     /*

... */

次の例は正しくないプログラム片である(共用体型が関数 f の中で可視ではないから。

struct t1 { int m; };

struct t2 { int m; };

int f(struct t1 * p1, struct t2 * p2)

 {

if (p1->m < 0)

p2->m = -p2->m;

   return

p1->m;

 }

 int

g()

 {

   union

{

struct t1 s1;

struct t2 s2;

   }

u;

   /*

... */

return f(&u.s1, &u.s2);

}

前方参照  アドレス及び間接演算子(6.5.3.2),構造体指定子及び共用体指定子(6.7.2.1

6.5.2.4

後置増分及び後置減分演算子

制約  後置増分演算子又は後置減分演算子のオペランドは,実数型又はポインタ型の修飾版又は非修飾版

をもたなければならず,変更可能な左辺値でなければならない。

意味規則  後置++演算子の結果は,そのオペランドの値とする。結果を取り出した後,オペランドの値を

増分する(すなわち,適切な型の値 1 をそれに加える。

。制約,型,並びにポインタに対する型変換及び

演算の効果については,加減演算子及び複合代入の規定のとおりとする。オペランドに格納されている値


55

X 3010

:2003 (ISO/IEC 9899:1999)

     

を更新する副作用は,直前の副作用完了点から次の副作用完了点までの間に起こらなければならない。

後置--演算子は,オペランドの値を減分する(すなわち,適切な型の値 1 をそれから引く)点を除いて,

後置++演算子と同一とする。

前方参照  加減演算子(6.5.6),複合代入(6.5.16.2

6.5.2.5

複合リテラル

制約  型名はオブジェクト型又は大きさの分からない配列を指定しなければならないが,可変長配列型を

指定してはならない。

複合リテラルが指定する名前のないオブジェクトに含まれないオブジェクトに,初期化子で値を与えて

はならない。

複合リテラルが関数本体の外に出現した場合,初期化子並びに含まれる式はすべて定数式でなければな

らない。

意味規則  括弧で囲まれた型名とそれに続く波括弧で囲まれた初期化子の並びで構成される後置式を複合

リテラル(compound literal)と呼ぶ。複合リテラルは,初期化子並びで与えられる値をもつ名前のないオ

ブジェクトを与える(

80

)

型名が大きさの分からない配列を指定している場合,6.7.8 で規定するとおりに初期化子の並びによって

大きさが決まる。さらに,この場合の複合リテラルの型は完全にされた配列型とする。そうでない場合(型

名がオブジェクト型を指定する場合)

,複合リテラルの型は型名で指定されたものとする。いずれの場合も

結果は左辺値とする。

複合リテラルの値は,初期化子並びで初期化された名前のないオブジェクトの値とする。複合リテラル

が関数本体の外側に出現した場合,オブジェクトは静的記憶域期間をもつ。そうでない場合,それを囲む

ブロックに結び付けられた自動記憶域期間をもつ。

6.7.8

で規定する初期化子並びのすべての意味規則及び制約を複合リテラルにも適用する(

81

)

文字列リテラルと const 修飾型の複合リテラルは,同じオブジェクトを指し示してもよい(

82

)

1.  ファイル有効範囲での定義

int *p = (int []){2, 4};

は,二つの int をもつ配列の最初の要素を指すように p を初期化する。最初の要素は値 2 をも

ち,2 番目の要素は値 4 をもつ。この複合リテラル中の式は定数でなければならない。この複

合リテラルによって生成される名前のないオブジェクトは静的記憶域期間をもつ。

2.  対照的に次のプログラムでは,

void f(void)

 {

   int

*p;

   /*

... */

───────────────────────────────────────────────

(80)

これはキャスト式とは異なる。例えば,キャストはスカラ型か void 型への変換しか指示できない。

また,キャスト式の結果は左辺値とはなり得ない。

(81)

例えば,明示的な初期化子をもたない部分オブジェクトは 0 に初期化される。

(82)

このことは,文字列リテラルと const 修飾型の複合リテラルが同じか重なり合った記憶域をもつよ

うな実装を許している。


56

X 3010

:2003 (ISO/IEC 9899:1999)

     

p = (int [2]){*p};

   /*

... */

}

p

には二つの int をもつ配列の最初の要素のアドレスが代入される。最初の要素は p が直前に

指していた値をもち,2 番目の要素は値 0 をもつ。この複合リテラル中の式は,定数である必

要はない。この複合リテラルによって生成される名前のないオブジェクトは自動記憶域期間を

もつ。

3.  指示付きの初期化子を複合リテラルと組み合わせることができる。複合リテラルを用いて生成

された構造体オブジェクトは,メンバの順番に依存することなく,関数に渡すことができる。

drawline((struct point){.x=1, .y=1},

(struct point){.x=3, .y=4});

又は drawline が構造体 point へのポインタを期待している場合は,次のように書く。

drawline(&(struct point){.x=1, .y=1},

&(struct point){.x=3, .y=4});

4.  読取り専用の複合リテラルは次のように書くことができる。

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}

5.  次の三つの式は異なる意味をもつ。

"/tmp/fileXXXXXX"

 (char

[]){"/tmp/fileXXXXXX"}

(const char []){"/tmp/fileXXXXXX"}

最初の式は,常に静的記憶域期間をもち,char の配列という型をもつが,変更可能である必

要はない。後の二つの式は関数本体の内部に出現した場合,自動記憶域期間をもち,最初から

2

番目の式は変更可能である。

6.  文字列リテラルと同様に,const 修飾型の複合リテラルは読取り専用記憶域に格納でき,共有す

ることもできる。例えば,

(const char []){"abc"} == "abc"

はリテラルの記憶域が共有されていれば,結果として 1 となりうる。

7.  複合リテラルは名前がないので,単一の複合リテラルで循環するオブジェクトを指定すること

はできない。例えば,次に示す名前付けられたオブジェクト endless_zeros の代わりに,関

数実引数として使うことができる自己参照する複合リテラルをプログラムで書く方法はない。

struct int_list { int car; struct int_list *cdr; };

struct int_list endless_zeros = {0, &endless_zeros};

 eval(endless_zeros);

8.  各複合リテラルは,その有効範囲においてオブジェクトを一つしか生成しない。

struct s { int i; };

int f (void)

 {

struct s *p = 0, *q;

int j = 0;


57

X 3010

:2003 (ISO/IEC 9899:1999)

     

 again:

q = p, p = &((struct s){ j++ });

if (j < 2) goto again;

return p == q && q->i == 1;

}

関数 f()は常に値 1 を返す。

明示的な goto 文及びラベル付き文の代わりに繰返し文が使われた場合,名前のないオブジ

ェクトの生存期間はループ本体だけとなる。ループの次の繰返しの入り口では,p は不定な値

をもち,結果として動作は未定義となる。

前方参照  型名(6.7.6),初期化(6.7.8

6.5.3

単項演算子

構文規則

単項式:

後置式

                                ++

単項式

                                --

単項式

単項演算子    キャスト式

                                sizeof

単項式

                                sizeof  (

型名    )

単項演算子:次のいずれか

                                & * + - ~ !

6.5.3.1

前置増分及び前置減分演算子

制約  前置増分演算子又は前置減分演算子のオペランドは,実数型又はポインタ型の修飾版又は非修飾版

をもたなければならず,変更可能な左辺値でなければならない。

意味規則  前置++演算子はオペランドの値を増分する。その結果は,増分された後のオペランドの新しい

値とする。式++E は,(E+=1)と等価とする。制約,型,副作用,並びにポインタに対する型変換及び演

算の効果については,加減演算子及び複合代入の規定のとおりとする。前置--演算子は,オペランドの値

を減分する点を除いて,前置++演算子と同一とする。

前方参照  加減演算子(6.5.6),複合代入(6.5.16.2

6.5.3.2

アドレス及び間接演算子

制約  単項&演算子のオペランドは,関数指示子,[]演算子若しくは単項*演算子の結果,又は左辺値でな

ければならない。左辺値の場合,ビットフィールドでもなく,register 記憶域クラス指定子付きで宣言

されてもいないオブジェクトを指し示さなければならない。

単項*演算子のオペランドは,ポインタ型をもたなければならない。

意味規則  単項&演算子は,そのオペランドのアドレスを返す。オペランドが型“∼型”をもっている場

合,結果は,型“∼型へのポインタ”をもつ。オペランドが,単項*演算子の結果の場合,*演算子も&演

算子も評価せず,両演算子とも取り除いた場合と同じ結果となる。ただし,その場合でも演算子に対する

制約を適用し,結果は左辺値とならない。同様に,オペランドが[]演算子の結果の場合,単項&演算子と,


58

X 3010

:2003 (ISO/IEC 9899:1999)

     

[]

演算子が暗黙に意味する単項*演算子は評価されず,&演算子を削除し[]演算子を+演算子に変更した場

合と同じ結果となる。これら以外の場合,結果はそのオペランドが指し示すオブジェクト又は関数へのポ

インタとなる。

単項*演算子は,間接参照を表す。オペランドが関数を指している場合,その結果は関数指示子とする。

オペランドがオブジェクトを指している場合,その結果はそのオブジェクトを指し示す左辺値とする。オ

ペランドが型“∼型へのポインタ”をもつ場合,その結果は型“∼型”をもつ。正しくない値がポインタ

に代入されている場合,単項*演算子の動作は,未定義とする(

83

)

前方参照  記憶域クラス指定子(6.7.1),構造体指定子及び共用体指定子(6.7.2.1

6.5.3.3

単項算術演算子

制約  単項+演算子及び単項-演算子のオペランドは,算術型をもたなければならない。~演算子のオペラ

ンドは,整数型をもたなければならない。!演算子のオペランドは,スカラ型をもたなければならない。

意味規則  単項+演算子の結果は,その(拡張された)オペランドの値とする。オペランドに対して整数

拡張を行い,その結果は,拡張された型をもつ。

単項-演算子の結果は,その(拡張された)オペランドの符号を反転した値とする。オペランドに対し

て整数拡張を行い,その結果は,拡張された型をもつ。

~演算子の結果は,その(拡張された)オペランドのビット単位の補数とする(すなわち,結果の各ビ

ットは,拡張されたオペランドの対応するビットがセットされていない場合,そしてその場合に限り,セ

ットされる。

。オペランドに対して整数拡張を行い,その結果は,拡張された型をもつ。拡張された型が

符号無し整数型である場合,~E はその型で表現可能な最大値から E を減算した値と等価とする。

論理否定演算子!の結果は,そのオペランドの値が 0 と比較して等しくない場合 0 とし,等しい場合 1

とする。結果の型は,int とする。式!E は,(0==E)と等価とする。

6.5.3.4

sizeof

演算子

制約  sizeof 演算子は,関数型若しくは不完全型をもつ式,それらの型の名前を括弧で囲んだもの,又

はビットフィールドメンバを指し示す式に対して適用してはならない。

意味規則  sizeof 演算子の結果は,そのオペランドの大きさ(バイト数)とする。オペランドは,式,

又は括弧で囲まれた型の名前のいずれかとする。その大きさは,オペランドの型によって決定する。結果

は,整数とする。オペランドの型が可変長配列型である場合,オペランドを評価する。そうでない場合,

オペランドは評価せず,その結果は,整数定数とする。

型 char,unsigned char 若しくは signed char(又はそれらの修飾版)をもつオペランドに適用

した場合の結果は,1 とする。配列型をもつオペランドに適用した場合の結果は,その配列中の総バイト

───────────────────────────────────────────────

(83)

&*E

は E と等価であり(E が空ポインタであっても)

,&(E1[E2])は((E1)+(E2))と等価である。

E

が単項&演算子の正しいオペランドとなる関数指示子又は左辺値の場合,*&E は E に等しい関数

指示子又は左辺値である。*P が左辺値であり,かつ T がオブジェクトポインタ型の名前である場

合,キャストを含む式*(T)P は,T が指すものと適合する型をもつ左辺値である。

単項*演算子によるポインタ参照をする場合の正しくない値には,空ポインタ,指されるオブジ

ェクトの型に対して正しく境界調整されていないアドレス,そしてその生存期間が終了してしまっ

ているオブジェクトのアドレスなどがある。


59

X 3010

:2003 (ISO/IEC 9899:1999)

     

数とする(

84

)

。構造体型又は共用体型をもつオペランドに適用した場合の結果は,内部及び末尾の詰め物部

分を含めたオブジェクトの総バイト数とする。

結果の値は,処理系定義とする。その型(符号無し整数型)は,ヘッダ<stddef.h>(及び,その他の

ヘッダ)で定義される size_t とする。

1.  sizeof 演算子の主な用途は,記憶域割付け及び入出力システムといったルーチンとのやりと

りにある。記憶域割付け関数は,記憶域を割り付けるオブジェクトの大きさ(バイト数)を受

け取り,void へのポインタを返すであろう。例えば,次のとおりである。

extern void *alloc(size_t);

double *dp = alloc(sizeof *dp);

alloc

関数の実装は,

alloc

関数の返却値が double を指すポインタに型変換できるように,

適切に境界調整されていることを保証しなければならない。

2.  sizeof 演算子のもう一つの用途は,次のようにして配列の要素の個数を求めることである。

sizeof array / sizeof array[0]

3.  この例では,可変長配列型の大きさを計算し,関数から返している。

#include <stddef.h>

size_t fsize3(int n)

 {

   char

b[n+3];

  //

可変長配列

return sizeof b;

//

実行時に決まる sizeof

 }

 int

main()

 {

   size_t

size;

size = fsize3(10);

// fsize3

は 13 を返す

   return

0;

 }

前方参照  型名(6.7.6),共通の定義<stddef.h>(7.17),構造体指定子及び共用体指定子(6.7.2.1),宣

言(6.7

,配列宣言子(6.7.5.2

6.5.4

キャスト演算子

構文規則

キャスト式:

単項式

                                (

型名    )    キャスト式

制約  型名が void 型を指定する場合を除いて,型名はスカラ型の修飾版又は非修飾版を指定しなければ

───────────────────────────────────────────────

(84)

配列型又は関数型をもつと宣言された仮引数に適用する場合,sizeof 演算子は,型調整された(ポ

インタ)型の大きさを与える(6.9.1 参照)


60

X 3010

:2003 (ISO/IEC 9899:1999)

     

ならず,オペランドは,スカラ型をもたなければならない。

6.5.16.1

の制約で許されるものを除いた,ポインタを含む型変換は,明示的なキャストで指定しなければ

ならない。

意味規則  括弧で囲まれた型名に続く式は,式の値を指定された型に型変換する。この構文をキャスト

(cast)と呼ぶ(

85

)

。型変換を指定しないキャストは,式の型又は値に対して何の効果ももたない(

86

)

前方参照  型名(6.7.6),関数宣言子(関数原型を含む)(6.7.5.3),単純代入(6.5.16.1),等価演算子(6.5.9

6.5.5

乗除演算子

構文規則

乗除式:

キャスト式

乗除式    *    キャスト式

乗除式    /    キャスト式

乗除式    %    キャスト式

制約  各オペランドは,算術型をもたなければならない。%演算子のオペランドは,整数型をもたなけれ

ばならない。

意味規則  通常の算術型変換をオペランドに適用する。

2

項*演算子の結果は,オペランドの積とする。

/

演算子の結果は,第 1 オペランドを第 2 オペランドで除した商とし,%演算子の結果は剰余とする。両

演算子とも,第 2 オペランドの値が 0 の場合,その動作は未定義とする。

整数同士の除算の場合,/演算子の結果は,代数的な商から小数部を切り捨てた値とする(

87

)

。商 a/b が

表現できる場合,式(a/b)*b+a%b は,a に等しくなければならない。

6.5.6

加減演算子

構文規則

加減式:

乗除式

加減式    +    乗除式

加減式    -    乗除式

制約  加算の場合,両オペランドが算術型をもつか,又は一方のオペランドがオブジェクト型へのポイン

タで,もう一方のオペランドの型が整数型でなければならない。

(増分は 1 の加算に等しい。

減算の場合,次のいずれかの条件を満たさなければならない。

−  両オペランドが算術型をもつ。

−  両オペランドが適合するオブジェクト型の修飾版又は非修飾版へのポインタである。

───────────────────────────────────────────────

(85)

キャストは左辺値を結果として返さない。したがって,修飾型へのキャストは,その型の非修飾版

へのキャストと同じ効果をもつ。

(86)

式の値が,キャストで指定した型が要求する精度や範囲を超えて表現される場合(6.3.1.8 参照)

,式

の型が指定された型と同じであるとしても,キャストは型変換を指定する。

(87)

これは,

“0 方向への切捨て”とも呼ぶ。


61

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  左オペランドがオブジェクト型へのポインタで,右オペランドの型が整数型である。

(減分は 1 の減算

に等しい。

意味規則  両オペランドが算術型をもつ場合,通常の算術型変換をそれらに適用する。

2

項+演算子の結果は,両オペランドの和とする。

2

項-演算子の結果は,第 1 オペランドから第 2 オペランドを引いた結果の差とする。

これらの演算子に関しては,配列の要素でないオブジェクトへのポインタは,要素型としてそのオブジ

ェクトの型をもつ長さ 1 の配列の最初の要素へのポインタと同じ動作をする。

整数型をもつ式をポインタに加算又はポインタから減算する場合,結果は,ポインタオペランドの型を

もつ。ポインタオペランドが配列オブジェクトの要素を指し,配列が十分に大きい場合,その結果は,そ

の配列の要素を指し,演算結果の要素と元の配列要素の添字の差は,整数式の値に等しい。すなわち,式

P

が配列オブジェクトの

i

番目の要素を指している場合,式(P)+N(N+(P)と等しい)及び(P)-N(N は値

n

をもつと仮定する。

)は,それらが存在するのであれば,それぞれ配列オブジェクトの

i

+

n

番目及び

i

n

番目の要素を指す。さらに,式 P が配列オブジェクトの最後の要素を指す場合,式(P)+1 はその配列オブ

ジェクトの最後の要素を一つ越えたところを指し,式 Q が配列オブジェクトの最後の要素を一つ越えたと

ころを指す場合,式(Q)-1 はその配列オブジェクトの最後の要素を指す。ポインタオペランド及びその結

果の両方が同じ配列オブジェクトの要素,又は配列オブジェクトの最後の要素を一つ越えたところを指し

ている場合,演算によって,オーバフローを生じてはならない。それ以外の場合,動作は未定義とする。

結果が配列オブジェクトの最後の要素を一つ越えたところを指す場合,評価される単項*演算子のオペラ

ンドとしてはならない。

二つのポインタを減算する場合,その両方のポインタは同じ配列オブジェクトの要素か,その配列オブ

ジェクトの最後の要素を一つ越えたところを指していなければならない。その結果は,二つの配列要素の

添字の差とする。結果の大きさは処理系定義とし,その型(符号付き整数型)は,ヘッダ<stddef.h>で

定義される ptrdiff_t とする。結果がその型のオブジェクトで表現可能でない場合,その動作は未定義

とする。言い換えれば,式 P と Q が,それぞれ配列オブジェクトの

i

番目と

j

番目の要素を指している場

合,式(P)-(Q)は,それが型 ptrdiff_t のオブジェクトに収まるのであれば,値

i

j

をもつ。さらに,

式 P が配列オブジェクトの要素,又は配列オブジェクトの最後の要素を一つ越えたところを指していて,

式 Q が同じ配列オブジェクトの最後の要素を指している場合,式(Q)+1 は,配列オブジェクトの要素を指

していないのだが,式((Q)+1)-(P)は,((Q)-(P))+1 及び-((P)-((Q)+1))と同じ値をもち,式 P が

配列オブジェクトの最後の要素を一つ越えたところを指している場合,値 0 をもつ(

88

)

例  ポインタ算術は,可変長配列型へのポインタにも定義される。

───────────────────────────────────────────────

(88)

ポインタ算術のもう一つの説明の方法は,最初にポインタを文字へのポインタに変換する方法であ

る。この考え方では,変換されたポインタに加算されるか,又は変換されたポインタから減算され

る整数式は,最初に本来指していたオブジェクトの大きさで乗算される。加減算の結果,得られる

ポインタは元の型へ逆変換される。同様に,ポインタ同士の減算の場合は,文字へのポインタ間の

差の結果を,本来指していたオブジェクトの大きさによって除算する。

この考え方によって,処理系が“最後の要素を一つ越えたところ”に関する要求を満足するには,

一つだけ余分なバイト(それはそのプログラムの他のオブジェクトに重なってもよい。

)をオブジェ

クトの直後に与えれば十分である。


62

X 3010

:2003 (ISO/IEC 9899:1999)

     

 {

int n = 4, m = 3;

  int

a[n][m];

int (*p)[m] = a;

// p == &a[0]

p += 1;

// p == &a[1]

(*p)[2] = 99;

// a[1][2] == 99

n = p - a;

// n == 1

 }

配列 a が既知で一定の大きさをもつ配列として宣言され,ポインタ p が a と同じ既知で一定の

大きさをもつ配列へのポインタとして宣言され,a を指している場合,結果はこの例と同じにな

る。

前方参照  共通の定義<stddef.h>(7.17),配列宣言子(6.7.5.2

6.5.7

ビット単位のシフト演算子

構文規則

シフト式:

加減式

シフト式    <<    加減式

シフト式    >>    加減式

制約  各オペランドは,整数型をもたなければならない。

意味規則  整数拡張を各オペランドに適用する。結果の型は,左オペランドを拡張した後の型とする。右

オペランドの値が負であるか,又は拡張した左オペランドの幅以上の場合,その動作は,未定義とする。

E1<<E2

の結果は,E1 を E2 ビット分左にシフトした値とする。空いたビットには 0 を詰める。E1 が符

号無し整数型をもつ場合,結果の値は,E1×2

E2

の,結果の型で表現可能な最大値より 1 大きい値を法と

する剰余とする。E1 が符号付き整数型と非負の値をもち,E1×2

E2

が結果の型で表現可能である場合,そ

れが結果の値となる。それ以外の場合,その動作は未定義とする。

E1>>E2

の結果は,E1 を E2 ビット分右にシフトした値とする。E1 が符号無し整数型をもつ場合,又は

E1

が符号付き整数型と非負の値をもつ場合,結果の値は,E1/2

E2

の商の整数部分とする。E1 が符号付き

整数型と負の値をもつ場合,結果の値は処理系定義とする。

6.5.8

関係演算子

構文規則

関係式:

シフト式

関係式    <    シフト式

関係式    >    シフト式

関係式    <=    シフト式

関係式    >=    シフト式

制約  次のいずれかの条件を満たさなければならない。

−  両オペランドが実数型をもつ。

−  両オペランドが適合するオブジェクト型の修飾版又は非修飾版へのポインタである。


63

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  両オペランドが適合する不完全型の修飾版又は非修飾版へのポインタである。

意味規則  両オペランドが算術型をもつ場合,通常の算術型変換を適用する。

関係演算子に関しては,配列の要素でないオブジェクトへのポインタは,要素型としてそのオブジェク

トの型をもつ長さ 1 の配列の最初の要素へのポインタと同じ動作をする。

二つのポインタを比較する場合,その結果は指されているオブジェクトのアドレス空間内の相対位置に

依存する。

オブジェクト型又は不完全型への二つのポインタがいずれも同じオブジェクトを指しているか,

いずれも同じ配列オブジェクトの最後の要素を一つ越えたところを指している場合,それらは比較して等

しいとする。指されている両オブジェクトが同一の集成体オブジェクトのメンバの場合,後方で宣言され

た構造体のメンバへのポインタは,その構造体中で前方に宣言されたメンバへのポインタと比較すると大

きく,大きな添字の値をもつ配列の要素へのポインタは,より小さな添字の値をもつ同じ配列の要素への

ポインタと比較すると大きいとする。同じ共用体オブジェクトのメンバへのポインタは,すべて等しいと

する。式 P が配列オブジェクトの要素を指しており,式 Q が同じ配列オブジェクトの最後の要素を指して

いる場合,ポインタ式 Q+1 は,P と比較してより大きいとする。その他のすべての場合,動作は未定義と

する。

<

(小さい)

,>(大きい)

,<=(以下)及び>=(以上)の各演算子は,指定された関係が真の場合は 1

を,偽の場合は 0 を返す(

89

)

。その結果は,型 int をもつ。

6.5.9

等価演算子

構文規則

等価式:

関係式

等価式    ==    関係式

等価式    !=    関係式

制約  次のいずれかの条件を満たさなければならない。

−  両オペランドは算術型をもつ。

−  両オペランドとも適合する型の修飾版又は非修飾版へのポインタである。

−  一方のオペランドがオブジェクト型又は不完全型へのポインタで他方が void の修飾版又は非修飾版

へのポインタである。

−  一方のオペランドがポインタで他方が空ポインタ定数である。

意味規則  ==(等しい)及び!=(等しくない)演算子は,関係演算子より優先順位が低いことを除いて関

係演算子と同じとする(

90

)

。各演算子は指定された関係が真の場合は 1 を,偽の場合は 0 を返す。その結果

は,型 int をもつ。どのようなオペランドの組に対しても,いずれか一方の関係が必ず真となる。

両オペランドが算術型をもつ場合,通常の算術型変換を適用する。複素数型の値は,互いの実部及び虚

部がそれぞれ等しい場合,そしてその場合に限り,等しいとする。異なる型領域に属する二つの算術型の

値は,通常の算術型変換によって決定される(複素数型の)結果の型への変換の結果が等しい場合,そし

───────────────────────────────────────────────

(89)

式 a<b<c は,通常の数学的な意味のようには解釈されない。構文が示しているように,(a<b)<c

を意味している。言い換えれば,

“a が b より小さい場合は 1 と c を比較し,それ以外の場合は 0

と c を比較する”ということである。

(90)

優先順位から,a<b == c<d は,a<b 及び c<d が同じ真理値をもつ場合に 1 となる。


64

X 3010

:2003 (ISO/IEC 9899:1999)

     

てその場合に限り,等しいとする。

そうでない場合,少なくとも一つのオペランドはポインタになる。一方のオペランドがポインタで,も

う一方のオペランドが空ポインタ定数の場合,空ポインタ定数をポインタの型へ型変換する。一方のオペ

ランドがオブジェクト型又は不完全型へのポインタで,もう一方が void の修飾版又は非修飾版へのポイ

ンタの場合,前者を後者の型へ型変換する。

二つのポインタは,次のいずれかの場合,そしてその場合に限り,等しいとする。

−  いずれも空ポインタである。

−  いずれも同じオブジェクト又は同じ関数を指すポインタである(一方がオブジェクトを指し,他方が

そのオブジェクトの先頭にある部分オブジェクトを指す場合も含む。

−  いずれも同じ配列オブジェクトの最後の要素を一つ越えたところを指している。

−  一方が配列オブジェクトの最後の要素を一つ越えたところを指すポインタであり,もう一方がアドレ

ス空間中でその配列オブジェクトの直後に続く異なる配列オブジェクトの先頭を指すポインタである

(

91

)

6.5.10

ビット単位の AND 演算子

構文規則

                AND

式:

等価式

                                AND

式    &    等価式

制約  各オペランドの型は,整数型でなければならない。

意味規則  オペランドに対して通常の算術型変換を適用する。

2

項&演算子の結果は,オペランドのビット単位の論理積とする(すなわち,型変換されたオペランドの

対応するビットが両者ともセットされている場合,そしてその場合に限り,結果のそのビットをセットす

る。

6.5.11

ビット単位の排他 OR 演算子

構文規則

排他OR式:

                                AND

排他OR式    ^  AND式

制約  各オペランドの型は,整数型でなければならない。

意味規則  オペランドに対して通常の算術型変換を適用する。

^

演算子の結果は,オペランドのビット単位の排他的論理和とする(すなわち,型変換されたオペラン

ドの対応するビットのいずれか一方だけがセットされている場合,そしてその場合に限り,結果のそのビ

ットをセットする。

───────────────────────────────────────────────

(91)

二つのオブジェクトは,大きな配列の隣接した要素である場合,メンバの間に詰め物がない構造体

の隣接したメンバである場合,又は全く関連をもたない場合でも,実装上の選択による配置などに

よって,記憶域で隣接していることがある。それ以前のポインタ演算で配列の境界を越えてアクセ

スするような未定義の動作を行った場合,それに続く比較の効果は未定義とする。


65

X 3010

:2003 (ISO/IEC 9899:1999)

     

6.5.12

ビット単位の OR 演算子

構文規則

                OR

式:

排他OR式

                                OR

式    |    排他OR式

制約  各オペランドの型は,整数型でなければならない。

意味規則  オペランドに対して通常の算術型変換を適用する。

|

演算子の結果は,オペランドのビット単位の論理和とする(すなわち,型変換されたオペランドの対

応するビットの少なくとも一方がセットされている場合,そしてその場合に限り,結果のそのビットをセ

ットする。

6.5.13

論理 AND 演算子

構文規則

論理AND式:

                                OR

論理AND式    &&    OR式

制約  各オペランドの型は,スカラ型でなければならない。

意味規則  &&演算子の結果の値は,両オペランドの値が 0 と比較してともに等しくない場合は 1,それ以

外の場合は 0 とする。結果の型は,int とする。

ビット単位の 2 項&演算子と異なり,&&演算子は左から右への評価を保証する。第 1 オペランドの評価

の直後を副作用完了点とする。第 1 オペランドの値が 0 と比較して等しい場合,第 2 オペランドは評価し

ない。

6.5.14

論理 OR 演算子

構文規則

論理OR式:

論理AND式

論理OR式    ||    論理AND式

制約  各オペランドの型は,スカラ型でなければならない。

意味規則  ||演算子の結果の値は,両オペランドを 0 と比較していずれか一方でも等しくない場合は 1,

それ以外の場合は 0 とする。結果の型は int とする。

ビット単位の|演算子と異なり,||演算子は左から右への評価を保証する。第 1 オペランドの評価の直

後を副作用完了点とする。第 1 オペランドの値が 0 と比較して等しくない場合,第 2 オペランドは評価し

ない。

6.5.15

条件演算子

構文規則

条件式:

論理OR式

論理OR式    ?    式    :    条件式

制約  第 1 オペランドの型は,スカラ型でなければならない。

第 2 及び第 3 オペランドの型は,次のいずれかの条件を満たさなければならない。


66

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  両オペランドの型が算術型である。

−  両オペランドの型が同じ構造体型又は共用体型である。

−  両オペランドの型が void 型である。

−  両オペランドが適合する型の修飾版又は非修飾版へのポインタである。

−  一方のオペランドがポインタであり,かつ他方が空ポインタ定数である。

−  一方のオペランドがオブジェクト型又は不完全型へのポインタであり,かつ他方が void の修飾版又

は非修飾版へのポインタである。

意味規則  第 1 オペランドを評価し,その評価の直後を副作用完了点とする。第 1 オペランドが 0 と比較

して等しくない場合だけ,第 2 オペランドを評価する。第 1 オペランドが 0 と比較して等しい場合だけ,

第 3 オペランドを評価する。第 2 又は第 3 オペランド(いずれか評価したほう)の値を結果とする。結果

の型は 6.5.15 の規定に従って型変換する(

92

)

。条件演算子の結果を変更するか,又は次の副作用完了点の後,

それにアクセスしようとした場合,その動作は,未定義とする。

第 2 及び第 3 オペランドの型がともに算術型ならば,通常の算術型変換をこれら二つのオペランドに適

用することによって決まる型を結果の型とする。

両オペランドの型がともに構造体型又は共用体型ならば,

結果の型はその型とする。両オペランドの型がともに void  型ならば,結果の型は void 型とする。

第 2 及び第 3 オペランドがともにポインタである場合,又は,一方が空ポインタ定数かつ他方がポイン

タである場合,

結果の型は両オペランドが指す型のすべての型修飾子で修飾された型へのポインタとする。

さらに,

両オペランドが適合する型へのポインタ又は適合する型の異なる修飾版へのポインタである場合,

結果の型は適切に修飾された合成型へのポインタとする。

一方のオペランドが空ポインタ定数である場合,

結果の型は他方のオペランドの型とする。これら以外の場合(一方のオペランドが void 又は void の修

飾版へのポインタである場合)

,結果の型は,適切に修飾された void 型へのポインタとする。

例  第 2 及び第 3 オペランドがポインタである場合の結果の共通の型は,二つの独立な段階を経て決

まる。例えば,結果の型の適切な型修飾子は,二つのポインタの型が適合するかどうかに依存し

ない。

次の宣言をしたとき,

const void *c_vp;

  void

*vp;

const int *c_ip;

volatile int *v_ip;

  int

*ip;

const char *c_cp;

次に示すものの右端の欄は,第 2 及び第 3 オペランドの型が最初の二つの欄(いずれかの順番で)

である場合の条件式の結果となる共通の型である。

c_vp

c_ip

const void *

v_ip

0

volatile int *

c_ip

v_ip

const volatile int *

vp

c_cp

const void *

───────────────────────────────────────────────

(92)

条件式は,左辺値を返さない。


67

X 3010

:2003 (ISO/IEC 9899:1999)

     

ip

c_ip

const int *

  vp

ip

void

*

6.5.16

代入演算子

構文規則

代入式:

条件式

単項式    代入演算子    代入式

代入演算子:  次のいずれか

                                =  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=

制約  代入演算子の左オペランドは,変更可能な左辺値でなければならない。

意味規則  代入演算子は,左オペランドで指し示されるオブジェクトに値を格納する。代入式は,代入後

の左オペランドの値をもつが,左辺値ではない。代入式の型は,左オペランドの型とする。ただし,左オ

ペランドの型が修飾型である場合は,左オペランドの型の非修飾版とする。左オペランドに格納されてい

る値を更新する副作用は,

直前の副作用完了点から次の副作用完了点までの間に起こらなければならない。

オペランドの評価順序は,未規定とする。代入演算子の結果を変更するか,又は次の副作用完了点の後,

それにアクセスしようとした場合,その動作は未定義とする。

6.5.16.1

単純代入

制約  次のいずれかの条件が成立しなければならない(

93

)

−  左オペランドの型が算術型の修飾版又は非修飾版であり,かつ右オペランドの型が算術型である。

−  左オペランドの型が右オペランドの型に適合する構造体型又は共用体型の修飾版又は非修飾版である。

−  両オペランドが適合する型の修飾版又は非修飾版へのポインタであり,かつ左オペランドで指される

型が右オペランドで指される型の型修飾子をすべてもつ。

−  一方のオペランドがオブジェクト型又は不完全型へのポインタであり,かつ他方が void の修飾版又

は非修飾版へのポインタである。さらに,左オペランドで指される型が,右オペランドで指される型

の型修飾子をすべてもつ。

−  左オペランドがポインタであり,かつ右オペランドが空ポインタ定数である。

−  左オペランドの型が_Bool 型であり,かつ右オペランドがポインタである。

意味規則  単純代入(simple assignment)(=)は,右オペランドの値を代入式の型に型変換し,左オペラ

ンドで指し示されるオブジェクトに格納されている値をこの値で置き換える。

オブジェクトに格納されている値を,何らかの形でそのオブジェクトの記憶域に重なる他のオブジェク

トを通してアクセスする場合,重なりは完全に一致していなければならない。さらに,二つのオブジェク

トの型は,適合する型の修飾版又は非修飾版でなければならない。そうでない場合,動作は未定義とする。

1.  次のプログラム片では,

int f(void);

 char

c;

───────────────────────────────────────────────

(93)

型修飾子に関するこれらの制約の非対称性は,左辺値を“式の値”に変更する型変換(6.3.2.1 参照)

の際に,その式の型分類から型修飾子が取り除かれることに起因する。


68

X 3010

:2003 (ISO/IEC 9899:1999)

     

 /*

... */

if ((c = f()) == -1)

   /*

... */

関数から返された int 型の値は,char 型に格納されるときに切り捨てられ,それから比較に

先立って int の幅に型変換されるかもしれない。単なる char と unsigned char の値の範

囲が同じである(さらに,char が int よりも幅の狭い)処理系では,型変換の結果が負にな

ることはないので,オペランドの比較は決して等しくはならない。可搬性を最大にするために,

変数 c は int 型として宣言することが望ましい。

2.  次のプログラム片では,

char c;

int i;

 long

l;

l = (c = i);

i

の値は代入式  c = i の型,すなわち char 型へ型変換される。その後,括弧内で囲まれた式

の値は外側の代入式の型,すなわち long int 型へ型変換される。

3.

const char **cpp;

 char

*p;

const char c = 'A';

cpp = &p;

//

制約違反

*cpp = &c;

//

正しい

*p = 0;

//

正しい

最初の代入は安全ではない。なぜなら,その後で正しいコードによって const オブジェクト c

の値を変更できるからである。

6.5.16.2

複合代入

制約  演算子+=及び-=の場合は,次のいずれかの条件を満たさなければならない。

−  左オペランドがオブジェクト型へのポインタであり,かつ右オペランドの型が整数型である。

−  左オペランドの型が算術型の修飾版又は非修飾版であり,かつ右オペランドの型が算術型である。

その他の演算子の場合,各オペランドの型は,対応する 2 項演算子に対して許される算術型でなければ

ならない。

意味規則  形式 E1

op

= E2

複合代入(compound assignment)は,左辺値 E1 がただ 1 回だけ評価される

点を除いて,単純代入式 E1 = E1

op

 (E2)

と同じとする。

6.5.17

コンマ演算子

構文規則

式:

代入式

式    ,    代入式


69

X 3010

:2003 (ISO/IEC 9899:1999)

     

意味規則  コンマ演算子は,左オペランドをボイド式として評価する。その評価の直後を副作用完了点と

する。次に右オペランドを評価する。コンマ演算子の結果は,右オペランドの型及び値をもつ(

94

)

。コンマ

演算子の結果を変更するか,又は次の副作用完了点の後でそれにアクセスしようとした場合,その動作は

未定義とする。

例  構文規則で示すとおり,コンマが区切り子である文脈(関数呼出しの実引数並びの中,及び初期

化子並びの中)では,コンマ演算子が現れることはない。一方,このような文脈でも括弧で囲ま

れた式の中,又は条件演算子の第 2 オペランドの中では使うことができる。関数呼出し

f(a, (t=3, t+2), c)

は,3 個の実引数をもち,2 番目の実引数の値は 5 である。

前方参照    初期化(6.7.8

6.6

定数式

構文規則

定数式:

条件式

補足説明  定数式は,実行時ではなく翻訳時に評価することができる。したがって,定数を使用してよい

ところならばどこでも使用してよい。

制約  定数式は,代入,増分,減分,関数呼出し又はコンマ演算子を含んではならない。ただし,定数式

が評価されない部分式(

95

)

に含まれている場合を除く。

定数式を評価した結果は,その型で表現可能な値の範囲内にある定数でなければならない。

意味規則  評価して定数になる式は,幾つかの文脈で必要となる。浮動小数点型の式を翻訳環境下で評価

する場合,その算術的な精度及び範囲は,式が実行環境下で評価される場合以上でなければならない。

整数定数式(integer constant expression)(

96

)

の型は,整数型でなければならない。整数定数式のオペラン

ドは,整数定数,列挙定数,文字定数,その結果が整数定数である sizeof 式又は浮動小数点定数でなけ

ればならない。この場合の浮動小数点定数は,キャストの直接のオペランドでなければならない。整数定

数式中のキャスト演算子は,sizeof 演算子のオペランドの一部である場合を除いて,算術型を整数型に

変換するものでなければならない。

初期化子中の定数式に対しては,更に広い自由度を許す。この場合の定数式の形,又はそれを評価した

結果は,次のいずれかでなければならない。

−  算術定数式

−  空ポインタ定数

−  アドレス定数

−  オブジェクト型に対するアドレス定数+整数定数式

−  オブジェクト型に対するアドレス定数-整数定数式

───────────────────────────────────────────────

(94)

コンマ演算子は,左辺値を返さない。

(95)

sizeof

演算子のオペランドは通常評価されない(6.5.3.4

(96)

整数定数式を使用しなければならないのは,構造体のビットフィールドメンバの大きさ,列挙定数

の値,配列の大きさ又は case 定数の値を指定する場合である。条件付き取込み前処理指令で使用

される整数定数式に適用されるその他の制約は,6.10.1 で規定する。


70

X 3010

:2003 (ISO/IEC 9899:1999)

     

算術定数式(arithmetic constant expression)は,算術型をもたなければならない。オペランドとして使え

るのは,整数定数,浮動小数点定数,列挙定数,文字定数及び sizeof 式だけとする。算術定数式中のキ

ャスト演算子は,その結果が整数定数である sizeof 演算子のオペランドの一部である場合を除いて,算

術型を算術型に変換するものでなければならない。

アドレス定数(address constant)は,空ポインタ,静的記憶域期間のオブジェクトを指し示す左辺値を

指すポインタ又は関数指示子を指すポインタとする。アドレス定数は,単項&演算子若しくは整数定数の

ポインタ型へのキャストによって明示的に生成されるか,又は配列型若しくは関数型の式の使用によって

暗黙に生成されたものでなければならない。配列添字演算子[],メンバアクセス演算子.及び->,アドレ

ス単項演算子&,間接単項演算子*,並びにポインタへのキャストは,アドレス定数の生成に使用してもよ

いが,これらの演算子を使用することによってオブジェクトの値をアクセスしてはならない。

処理系は,定数式の他の形式を許してもよい。

定数式の評価に対する意味規則は,定数でない式の場合と同じとする(

97

)

前方参照      初期化(6.7.8),配列宣言子(6.7.5.2

6.7

宣言

構文規則

宣言:

宣言指定子列    初期化宣言子並び

opt

;

宣言指定子列:

記憶域クラス指定子    宣言指定子列

opt

型指定子    宣言指定子列

opt

型修飾子    宣言指定子列

opt

関数指定子    宣言指定子列

opt

初期化宣言子並び:

初期化宣言子

初期化宣言子並び    ,    初期化宣言子

初期化宣言子:

宣言子

宣言子    =    初期化子

制約  宣言では,少なくとも一つの宣言子(関数の仮引数又は構造体若しくは共用体のメンバ以外のもの),

タグ又は列挙体のメンバを宣言しなければならない。

識別子が無結合である場合,その識別子の宣言(宣言子又は型指定子の中の)が同じ有効範囲及び同じ

名前空間の中で,二つ以上あってはならない。ただし,タグの宣言は除く(6.7.2.3 参照)

同じオブジェクト又は同じ関数についての同じ有効範囲の中のすべての宣言は,適合する型を指定しな

ければならない。

───────────────────────────────────────────────

(97)

したがって,次のような初期化では,

                static  int i = 2 || 1 / 0;

式は値 1 をもった有効な整数定数式である。


71

X 3010

:2003 (ISO/IEC 9899:1999)

     

意味規則  宣言は,幾つかの識別子の解釈及び属性を指定する。識別子の定義(definition)とは,宣言の

うち次のものをいう。

−  オブジェクトに対しては,そのオブジェクトの記憶域を確保する宣言

−  関数に対しては,関数本体を含む宣言(

98

)

−  列挙定数又は型定義名に対しては,その識別子の(唯一の)宣言

宣言指定子列は,結合,記憶域期間及び宣言子が表す実体の型の一部を示す指定子の列から成る。初期

化宣言子並びは,コンマで区切られた宣言子の列とし,各宣言子は,付加的な型情報,初期化子又はそれ

らの両方をもっていてもよい。宣言子は,

(もしあれば)宣言する識別子を含む。

オブジェクトの識別子が無結合で宣言されている場合,オブジェクトの型は,その宣言子の終わりまで

に,又は初期化宣言子の終わりまで(その宣言子が初期化子をもつとき)に,完全になっていなければな

らない。

(関数原型の場合も含めて)関数の仮引数の場合,完全型でなければならないのは型調整された型

6.7.5.3 参照)とする。

前方参照    初期化(6.7.8),宣言子(6.7.5),列挙型指定子(6.7.2.2

6.7.1

記憶域クラス指定子

構文規則

記憶域クラス指定子:

                                typedef

                extern

                static

                auto

                register

制約  一つの宣言の宣言指定子列の中で二つ以上の記憶域クラス指定子を与えてはならない(

99

)

意味規則  typedef 指定子は,構文的な都合だけから“記憶域クラス指定子”と呼ぶ。これについては,

6.7.7

で規定する。各種の結合及び記憶域期間の意味については,6.2.2 及び 6.2.4 で規定する。

オブジェクトの識別子が記憶域クラス指定子 register を用いて宣言されている場合,そのオブジェク

トへのアクセスを可能な限り高速にすべきであることを示唆する。この示唆が効果をもつ程度は,処理系

定義とする(

100

)

関数の識別子がブロック有効範囲で宣言される場合,extern 以外の明示的な記憶域クラス指定子をも

ってはならない。

───────────────────────────────────────────────

(98)

関数定義は異なる構文をもつが,これについては,6.9.1 で規定する。

(99)

“今後の言語の方針”

6.11.5)参照。

(100)

処理系は,register 宣言を単に auto 宣言として扱ってもよい。しかし,アドレス付け可能な記

憶域が実際に使われるかどうかにかかわらず,記憶域クラス指定子  register を伴って宣言され

たオブジェクトのどの部分のアドレスも,

6.5.3.2 で述べる単項&演算子によって)

明示的にも又は

6.3.2.1 で述べる配列名のポインタへの変換によって)暗黙にも,計算することはできない。した

がって,記憶域クラス指定子  register を伴って宣言された配列に適用できる演算子は,sizeof

だけである。


72

X 3010

:2003 (ISO/IEC 9899:1999)

     

集成体又は共用体のオブジェクトが typedef 以外の記憶域クラス指定子を用いて宣言されたとき,結

合に関するものを除いて,記憶域クラス指定子による性質をオブジェクトのメンバにも適用する。また再

帰的に集成体又は共用体であるすべてのメンバオブジェクトに適用する。

前方参照    型定義(6.7.7

6.7.2

型指定子

構文規則

型指定子:

                                void

                char

                short

                int

                long

                float

                double

                signed

                unsigned

                _Bool

                _Complex

                _Imaginary

構造体共用体指定子

列挙型指定子

型定義名

制約  それぞれの宣言の宣言指定子列の中で,又はそれぞれの構造体宣言及び型名の型指定子型修飾子並

びの中で,少なくとも一つの型指定子を指定しなければならない。型指定子の並びは,次に示すもののい

ずれか一つでなければならない(1 行に二つ以上の組がある場合,コンマで区切ってある。

。型指定子は,

いかなる順序で現れてもよく,更に,他の宣言指定子と混合してもよい。

−  void

−  char

−  signed char

−  unsigned char

−  short,signed short,short int,signed short int

−  unsigned short,unsigned short int

−  int,signed,signed int

−  unsigned,unsigned int

−  long,signed long,long int,signed long int

−  unsigned long,unsigned long int

−  long long,signed long long,long long int,signed long long int

−  unsigned long long,unsigned long long int

−  float


73

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  double

−  long double

−  _Bool

−  float _Complex

−  double _Complex

−  long double _Complex

−  float _Imaginary

−  double _Imaginary

−  long double _Imaginary

−  構造体共用体指定子

−  列挙型指定子

−  型定義名

型指定子_Complex 及び_Imaginary は,処理系がそれらを提供しない場合は使用してはならない(

101

)

意味規則  構造体,共用体及び列挙型の指定子は,6.7.2.16.7.2.3 で規定する。型定義名の宣言は,6.7.7

で規定する。他の型の性質は,6.2.5 で規定する。

コンマで区切られているそれぞれの組は,同じ型を表す。ただし,ビットフィールドの場合,型指定子

int

が signed int と同じ型を表すか,unsigned int と同じ型を表すかは処理系定義とする。

前方参照    型定義(6.7.7),構造体指定子及び共用体指定子(6.7.2.1),タグ(6.7.2.3),列挙型指定子(6.7.2.2

6.7.2.1

構造体指定子及び共用体指定子

構文規則

構造体共用体指定子:

構造体共用体    識別子

opt

 {

メンバ宣言並び    }

構造体共用体    識別子

構造体共用体:

                                struct

                                union

メンバ宣言並び:

メンバ宣言

メンバ宣言並び    メンバ宣言

メンバ宣言:

型指定子型修飾子並び    メンバ宣言子並び    ;

型指定子型修飾子並び:

型指定子    型指定子型修飾子並び

opt

型修飾子    型指定子型修飾子並び

opt

メンバ宣言子並び:

───────────────────────────────────────────────

(101)

処理系は虚数型を提供しなくてもよい。フリースタンディング処理系では複素数型を提供しなくて

もよい。


74

X 3010

:2003 (ISO/IEC 9899:1999)

     

メンバ宣言子

メンバ宣言子並び    ,    メンバ宣言子

メンバ宣言子:

宣言子

宣言子

opt

    :

定数式

制約  構造体及び共用体は,不完全型又は関数型のメンバを含んではならない。したがって,構造体及び

共用体は,その型自身のインスタンスを含んではならない(しかし,その型自身へのポインタは含んでも

よい。

。例外的に,二つ以上の名前付きメンバをもつ構造体の最後のメンバは不完全配列型をもってもよ

い。そのような構造体[又はそのような構造体をメンバとしてもつ共用体(再帰的に含む場合でも)

]を構

造体メンバ又は配列要素にしてはならない。

ビットフィールドの幅を指定する式は,整数定数式でなければならない。その値は,0 以上でなければ

ならず,コロン及び式が省略された場合,指定された型のオブジェクトがもつビット数を超えてはならな

い。値が 0 の場合,その宣言に宣言子があってはならない。

ビットフィールドの型は,修飾版又は非修飾版の_Bool,signed int,unsigned int 又は他の処理

系定義の型でなければならない。

意味規則  構造体は,メンバの列から成る型とし,メンバの記憶域は,並べられた順に割り付ける(6.2.5

参照)

。共用体は,メンバの列から成る型とし,メンバの記憶域は重なり合う。

構造体及び共用体の指定子は,同一の形式をもつ。

構造体共用体指定子の中にメンバ宣言並びがある場合,翻訳単位内での新しい型を宣言する。メンバ宣

言並びは,構造体又は共用体のメンバの宣言の列とする。メンバ宣言並びが名前付きのメンバを含まない

場合,その動作は未定義とする。型は,並びを終了する}までは不完全型とする。

構造体又は共用体のメンバの型は,可変修飾型(

102

)

を除くいかなるオブジェクト型であってもよい。さ

らに,メンバは,ビット数(もしあれば符号ビットも含めて)の指定付きで宣言してもよい。ビット数が

指定されたメンバを

ビットフィールド(bit field)(

103

)

と呼ぶ。その(ビット数を示す)幅の直前には,コ

ロンを置く。

ビットフィールドは,指定された個数のビットから成る符号付き又は符号無しの整数型として解釈する

(

104

)

。値 0 又は 1 を幅 1 以上の_Bool 型のビットフィールドに設定した場合,ビットフィールドの値は設

定された値と比較して等しくなければならない。

処理系は,ビットフィールドを保持するに十分な大きさの任意のアドレス付け可能な記憶域単位を割り

付けてよい。十分な領域が残っている場合,構造体内のビットフィールドの直後に続く別のビットフィー

ルドは,同じ単位の隣接したビットに詰め込まなければならない。十分な領域が残っていない場合,入り

───────────────────────────────────────────────

(102)

構造体及び共用体は可変修飾型のメンバをもつことができない。なぜなら,6.2.3 での定義により

メンバ名は通常の識別子ではないからである。

(103)

単項&(アドレス)演算子は,ビットフィールドオブジェクトに適用できない。したがって,ビッ

トフィールドオブジェクトへのポインタ又は配列は存在しない。

(104)

6.7.2

の規定によって,使用された実際の型指定子が,int か又は int として定義されている型定

義名である場合,ビットフィールドが符号付きか符号無しかは処理系定義である。


75

X 3010

:2003 (ISO/IEC 9899:1999)

     

切らなかったビットフィールドを次の単位に入れるか,又は隣接した単位の境界をまたがせるかは,処理

系定義とする。単位内のビットフィールド割付けの順序(上位から下位か又は下位から上位か)は,処理

系定義とする。アドレス付け可能な記憶域単位の境界調整は,未規定とする。

宣言子がなく,コロン及び幅だけをもつビットフィールド宣言は,名前のないビットフィールド(

105

)

示す。この特別な場合として,幅が 0 のビットフィールド構造体メンバは,前のビットフィールド(もし

あれば)が割り付けられていた単位に,それ以上のビットフィールドを詰め込まないことを指定する。

構造体又は共用体オブジェクトのビットフィールド以外の各メンバの境界は,その型に適した処理系定

義の方法で調整する。

構造体オブジェクト内では,非ビットフィールドメンバ及びビットフィールドが置かれる単位は,宣言

された順に増加するアドレスをもつ。構造体オブジェクトへのポインタは,適切に変換すれば,その先頭

メンバ(又はビットフィールドならば,それが置かれた単位)を指す。さらに,その逆も成り立つ。構造

体オブジェクトの中に名前のない詰め物があってもよいが,先頭には名前のない詰め物があってはならな

い。

共用体の大きさは,最大のメンバを保持するのに十分な大きさとする。どんなときでも,高々一つのメ

ンバの値だけが共用体オブジェクトに格納できる。共用体オブジェクトへのポインタは,適切に変換すれ

ば,そのそれぞれのメンバ(又はメンバがビットフィールドならば,それが置かれた単位)を指す。さら

に,その逆も成り立つ。

構造体又は共用体の最後に名前のない詰め物があってもよい。

特別な場合として,二つ以上の名前付きメンバをもつ構造体の最後のメンバは,不完全配列型をもって

もよい。これを

フレキシブル配列メンバ(flexible array member)と呼ぶ。二つの例外を除いて,フレキシ

ブル配列メンバは無視される。一つ目は,構造体の大きさは,フレキシブル配列メンバを未規定の長さの

配列に置き換えて,それ以外は元のままとした構造体の最後のメンバのオフセットに等しいとする(

106

)

二つ目は,.(又は->)演算子がフレキシブル配列メンバをもつ構造体(又はその構造体へのポインタ)

を左オペランドとしてもち,かつ右オペランドがそのメンバであるとき,その動作は,構造体の大きさが

現在アクセスされているオブジェクトの大きさより大きくならないという条件のもとで,そのメンバが同

じ要素型をもつ最大の大きさの配列で置き換えられた場合と同じとする。このとき,たとえ置き換えられ

た配列のオフセットがそのメンバのオフセットと異なるとしても,

そのメンバのオフセットは変更しない。

置き換えられた配列が要素をもたないとき,それはただ一つの要素をもつのと同じ規則で動作する。しか

し,その要素にアクセスした場合,又はその要素を一つ越えたポインタを生成した場合,その動作は未定

義とする。

例  すべての配列メンバが同様に境界を調整されると仮定すると,次の宣言について

struct s { int n; double d[]; };

struct ss { int n; double d[1]; };

次の三つの式は,

───────────────────────────────────────────────

(105)

名前のないビットフィールド構造体メンバは,外部から強制された配置に合わせるための詰め物と

して便利である。

(106)

長さが未規定であるため,処理系は,配列であるメンバの長さに応じてそのメンバの境界調整を異

ならせることができる。


76

X 3010

:2003 (ISO/IEC 9899:1999)

     

sizeof (struct s)

offsetof(struct s, d)

offsetof(struct ss, d)

同じ値をもつ。  構造体 struct s は,一つのフレキシブル配列メンバ d をもつ。

sizeof (double)

が 8 である場合,次のコードが実行されて,

struct s *s1;

struct s *s2;

s1 = malloc(sizeof (struct s) + 64);

s2 = malloc(sizeof (struct s) + 46);

二つの malloc 呼出しが成功したとき,s1 と s2 で指されるオブジェクトは,識別子が次のよう

に宣言された場合と同じ規則で動作する。

struct { int n; double d[8]; } *s1;

struct { int n; double d[5]; } *s2;

さらに,次の代入は,

s1 = malloc(sizeof (struct s) + 10);

s2 = malloc(sizeof (struct s) +  6);

次の宣言があった場合と同じ規則で動作する。

struct { int n; double d[1]; } *s1, *s2;

このとき,

double *dp;

dp = &(s1->d[0]);

  // 正しい

*dp = 42;

  // 正しい

dp = &(s2->d[0]);

  // 正しい

*dp = 42;

  // 未定義の動作

次の代入について

*s1 = *s2;

メンバ n だけはコピーされるが,配列の要素はコピーされない。同様に,

struct  s    t1  =  {  0  };          //

正しい

struct  s    t2  =  {  2  };          //

正しい

struct ss   tt = { 1, { 4.2 }};//

正しい

struct s    t3 = { 1, { 4.2 }}; //

正しくない: 4.2 が初期化する対象はない

t1.n  =  4;                          //

正しい

t1.d[0]  =  4.2;                    //

未定義の動作

前方参照    タグ(6.7.2.3

6.7.2.2

列挙型指定子

構文規則

列挙型指定子:

                                enum

識別子

opt

    {

列挙子並び    }

                                enum

識別子

opt

    {

列挙子並び  , }


77

X 3010

:2003 (ISO/IEC 9899:1999)

     

                                enum

識別子

列挙子並び:

列挙子

列挙子並び    ,    列挙子

列挙子:

列挙定数

列挙定数    =    定数式

制約  列挙定数の値を定義する式は,int 型で表現可能な値をもつ整数定数式でなければならない。

意味規則  列挙子並びの中の識別子は,型 int をもつ定数として宣言され,この型の定数が許されるとこ

ろならばどこに現れてもよい(

107

)

。=を含む列挙子は,その定数式の値をもつ列挙定数を定義する。最初の

列挙子に=がない場合,その列挙定数の値は 0 とする。=がない 2 番目以降の各列挙子は,直前の列挙定数

の値に 1 を加えて得られる定数式の値をもつ列挙定数を定義する。

(=をもつ列挙子を使用することによっ

て,同じ列挙体の中で複数の列挙定数の値が同じになってもよい。

)列挙体の列挙子は,そのメンバともい

う。

それぞれの列挙型は,char,符号付き整数型又は符号無し整数型と適合する型とする。型の選択は,処

理系定義とする(

108

)

。しかし,その型は列挙型のすべてのメンバの値を表現できなければならない。列挙

子の宣言の並びを終了する}までは列挙型は不完全型とする。

enum hue { chartreuse, burgundy, claret=20, winedark };

enum hue col, *cp;

col = claret;

cp = &col;

if (*cp != burgundy)

   /*

... */

この例は hue を列挙型タグにし,次にその型をもつオブジェクトとして col,その型をもつオ

ブジェクトへのポインタとして cp を宣言している。列挙された値の集合は,{0,1, 20, 21}である。

前方参照    タグ(6.7.2.3

6.7.2.3

タグ

制約  個々の型は 1 回だけその内容を定義できる。

列挙子並びをもたない次の形式である型指定子

        enum

識別子

は,その型が完全型になった後でだけ指定できる。

意味規則  同じ有効範囲をもち,かつ同じタグを使用する構造体型,共用体型又は列挙型のすべての宣言

───────────────────────────────────────────────

(107)

したがって,同じ有効範囲で宣言された列挙定数の識別子は,互いに違っていなければならず,通

常の宣言子で宣言された他の識別子とも違っていなければならない。

(108)

処理系はすべての列挙定数が指定された後で整数型の選択を行うことができる。


78

X 3010

:2003 (ISO/IEC 9899:1999)

     

は,同じ型を宣言する。型は,内容を定義する並びを終了する}までは不完全型(

109

)

とし,それ以降は完全

型とする。

異なる有効範囲をもつ又は異なるタグを使用する構造体型,共用体型又は列挙型の二つの宣言は別個の

型を宣言する。タグを含まない構造体型,共用体型又は列挙型のそれぞれの宣言は別個の型を宣言する。

型指定子の形式

構造体共用体  識別子

opt

 {

メンバ宣言並び    } (1)

又は

                enum

識別子    {    列挙子並び    }  (2)

若しくは

                enum

識別子    {    列挙子並び  , }  (3)

は,構造体型,共用体型又は列挙型を宣言する。その並びは

構造体の内容(structure content),共用体の内

容(union content)又は列挙体の内容(enumeration content)を定義する。識別子が指定された場合(

110

)

,こ

れに加えて,型指定子は識別子をその型のタグとして宣言する。

宣言の形式

構造体共用体    識別子    ;  (4)

は,構造体型又は共用体型を指定し,その型のタグとして識別子を宣言する(

111

)

型指定子の形式

構造体共用体    識別子

は,上記の[形式(1)∼(4)の]のいずれかの一部でない場合,かつタグとしての識別子の他の宣言

が不可視である場合,不完全構造体型又は不完全共用体型を宣言し,その型のタグとして識別子を宣言す

る(

111

)

型指定子の形式

構造体共用体    識別子

又は

                enum

識別子

は,上記の[形式(1)∼(4)の]いずれかの一部でない場合,かつタグとしての識別子の宣言が可視

である場合,その宣言と同じ型を指定し,タグの再宣言を行わない。

1.  この機構を使えば,自己参照する構造体の宣言が可能である。

struct tnode {

───────────────────────────────────────────────

(109)

不完全型は,その型のオブジェクトの大きさが必要でないときだけ使用できる。例えば構造体若し

くは共用体に対する指定子として型定義名を宣言するとき,構造体若しくは共用体へのポインタを

指定するとき,又は,構造体若しくは共用体を返す関数を宣言するときには,その型のオブジェク

トの大きさは必要ではない(不完全型については 6.2.5 を参照)

。その関数が呼び出される又は定義

されるときには完全型になっていなければならない。

(110)

識別子がない場合,翻訳単位内で,型は,それが一部となっている宣言によってだけ参照できる。

もちろん,それが型定義名の宣言であれば,後に続く宣言では型定義名をその指定された構造体型,

共用体型又は列挙型をもつオブジェクトの宣言に使用できる。

(111)

enum

については同様のことは指定できない。


79

X 3010

:2003 (ISO/IEC 9899:1999)

     

   int

count;

struct tnode *left, *right;

 };

この例は,一つの整数及び同じ型のオブジェクトへの二つのポインタを含む構造体を宣言して

いる。いったん,この宣言が与えられると,次のような宣言ができる。

struct tnode s, *sp;

これは,

その型のオブジェクト s 及びその型のオブジェクトへのポインタ sp を宣言している。

このような宣言では,式 sp->left は,sp が指すオブジェクトの struct tnode への左の

ポインタを参照し,式 s.right->count は,s の struct tnode への右のポインタが指す

オブジェクトのメンバである count を指し示している。

同じことを typedef 機構を用いて,次のように書くこともできる。

typedef struct tnode TNODE;

struct tnode {

   int

count;

TNODE *left, *right;

 };

TNODE s, *sp;

2.  相互参照する構造体の組を宣言するために,タグを前もって宣言して使用する例を説明する。

宣言

struct s1 { struct s2 *s2p; /*

... */ }; // D1

struct s2 { struct s1 *s1p; /*

... */ }; // D2

は,互いに他方を指すポインタを含む構造体の対を指定する。しかし,s2 がそれを囲む有効範

囲でタグとして既に宣言されている場合,宣言 D1 はそれを参照し,D2 で宣言されるタグ s2

を参照しない。このような文脈の影響を除くために,宣言

struct s2;

を D1 の前に挿入する方法がある。これは,内側の有効範囲で新しいタグ s2 を宣言する。宣言

D2

で新しい型の仕様を完全にする。

前方参照    型定義(6.7.7),宣言子(6.7.5),配列宣言子(6.7.5.2

6.7.3

型修飾子

構文規則

型修飾子:

                              const

                restrict

                volatile

制約  オブジェクト型又は不完全型から派生したポインタ型以外の型を restrict 修飾してはならない。

意味規則  修飾型に関連する性質は,左辺値である式に対してだけ意味をもつ(

112

)

───────────────────────────────────────────────

(112)

処理系は,volatileでないconstオブジェクトを,読取り専用記憶域に置いてもよい。さらに,処

理系はそのアドレスが使われないならば,

そのようなオブジェクトに記憶域を割り付けなくてもよい。


80

X 3010

:2003 (ISO/IEC 9899:1999)

     

一つの型指定子型修飾子並びの中に同じ型修飾子が(直接に又は一つ以上の typedef を介して)複数

回出現しても,その動作は 1 回だけ出現したときと同じとする。

const

修飾型で定義されたオブジェクトを,非 const 修飾型の左辺値を使って変更しようとした場合,そ

の動作は未定義とする。volatile 修飾型で定義されたオブジェクトを非 volatile 修飾型の左辺値を使って参

照しようとした場合,その動作は未定義とする(

113

)

volatile

修飾型をもつオブジェクトは,処理系に未知の方法で変更されてもよく,又はその他の未知の副

作用をもっていてもよい。したがって,volatile 修飾型をもつオブジェクトを参照するすべての式は,抽象

計算機の規則(5.1.2.3 で規定する)に厳密に従って評価しなければならない。さらに,そのオブジェクト

に最後に格納された値は,先に述べた未知の要因によって変更された場合を除いて,すべての副作用完了

点で抽象計算機の規則に従った値と一致しなければならない(

114

)

。volatile 修飾型のオブジェクトへのアク

セスをどのように構成するかは,処理系定義とする。

restrict

修飾されたポインタを使ってアクセスされるオブジェクトは,そのポインタと特別な結び付きを

もつ。6.7.3.1 で定義するこの結び付きがあるため,そのオブジェクトにアクセスするときには必ずそのポ

インタの値を直接的又は間接的に使わなければならならない(

115

)

(register 記憶域クラス指定子と同

様に)restrict 修飾子を用いることで最適化を促進することができる。規格合致プログラムを構成する

すべての前処理翻訳単位から restrict 修飾子を削除しても,その意味(すなわち,目に見える動作)は

変わらない。

配列型の指定が型修飾子を含む場合,それは要素の型を修飾するだけで,その配列型を修飾するのでは

ない。関数型の指定が型修飾子を含む場合,その動作は未定義とする(

116

)

二つの修飾型が適合するためには,双方が適合する型に同じ修飾を行ったものでなければならない。型

指定子又は型修飾子の並びにおける型修飾子の順序は,指定された型に影響を与えない。

1.  次のように宣言されたオブジェクトは,ハードウェアによって変更されることがあってもよい

が,代入したり,増分したり又は減分したりすることはできない。

extern const volatile int real_time_clock;

2.  次の宣言及び式は,型修飾子が集成体型を修飾する場合の動作を説明する。

const struct s { int mem; } cs = { 1 };

struct s ncs;

//

オブジェクト ncs は変更可能

typedef int A[2][3];

───────────────────────────────────────────────

(113)

この規則は,修飾型で定義されたもののような動作をするオブジェクトにも適用する。例えば,

(メ

モリ上に割り付けられた入出力アドレスのように)実際にはプログラム内のオブジェクトとして定

義されないものも含む。

(114)

volatile

宣言は,メモリ上に割り付けられた入出力ポートに相当するオブジェクト,又は非同期

的な割込み機構によってアクセスされるオブジェクトを記述するのに使用してもよい。そのように

宣言されたオブジェクトに対する操作は,式の評価の規則で許されている場合を除いて,処理系の

最適化によって削除又は順序の変更が行われてはならない。

(115)

例えば,malloc の返却値を単一のポインタに代入する文は,割付けオブジェクトとそのポインタ

とを結び付ける。

(116)

これらのことは,typedef の使用を通して起こりうる。


81

X 3010

:2003 (ISO/IEC 9899:1999)

     

const A a = {{4,5,6},{7,8,9}}; // const int

の配列の配列

 int

*pi;

const int *pci;

ncs = cs;

//

正しい

cs = ncs;

//

代入演算子の変更可能な左辺値の制約に違反

pi = &ncs.mem;

//

正しい

pi = &cs.mem;

//

代入演算子の型の制約に違反

pci = &cs.mem;

//

正しい

pi = a[0];

//

正しくない: a[0]は型“const int *”をもつ

6.7.3.1

restrict

の形式的定義  D を通常の識別子の宣言とし,この識別子は,型 T を指す restrict 修飾

されたポインタとしてオブジェクト P を指し示すものとする。

D

がブロックの内側に出現し,

かつその記憶域クラスが extern でない場合,

そのブロックを B で表す。

D

が関数定義の仮引数宣言並びに出現した場合,結び付けられたブロックを B で表す。それ以外の場合,

main

関数(又は,フリースタンディング環境でプログラム開始処理から呼び出される関数)のブロック

を B で表す。

ポインタ式 E がオブジェクト P を

ベースとする(based),と呼ぶのは,P が指していた配列オブジェク

トをコピーして,

(式 E の評価より前の B 中のある副作用完了点で)そのコピーを指すように P を変更す

ると,E の値が変わる場合とする(

117

)

。この“ベースとする”という関係は,ポインタ型をもつ式だけに対

して定義する。

L

を左辺値とする。&L は B の実行中に P をベースとするものとする。L を使って L が指し示すオブジェ

クト X の値をアクセスし,

(何らかの手段で)X が変更される場合,次の条件を適用する。

−  T が const 修飾型であってはならない。

−  X の値にアクセスするために使われる他のすべての左辺値は,P をベースとするアドレスをもたなけ

ればならない。

−  X を変更するすべてのアクセスは P も変更するとみなす(6.7.3.1 では)

−  P とは異なる restrict ポインタオブジェクト P2 がブロック B2 に結び付けられており,P2 をベースと

するポインタ式 E の値を P に代入する場合,B2 の実行が B より前に始まるか,又は B2 の実行がその

代入よりも前に完了するかでなければならない。

これらの条件を満たさない場合の動作は,未定義とする。

ここでの B の実行とは,プログラムの実行のうち,B に結び付けられた自動記憶域期間をもつスカラ型

のオブジェクトの生存期間に相当する部分を意味する。

restrict

を使うと,処理系は別名付けがあった場合に起こることを無視してよい。

1.  ファイル有効範囲の次の宣言は,

───────────────────────────────────────────────

(117)

言い換えれば,E は P そのものの値に依存し,P を介して間接的に参照されるオブジェクトの値に

は依存しない。例えば,識別子 p が型(int **restrict)をもつ場合,ポインタ式 p と p+1 は

p

が示す restrict ポインタオブジェクトをベースとする。しかし,ポインタ式*p と p[1]はそうな

らない。


82

X 3010

:2003 (ISO/IEC 9899:1999)

     

int * restrict a;

int * restrict b;

extern int c[];

a

,b 又は c のいずれか一つを使ってオブジェクトにアクセスし,プログラム中のどこかでそ

のオブジェクトを変更する場合,他の二つを使ってそのオブジェクトにアクセスすることがな

いことを明示する。

2.  次の例での関数仮引数宣言は,

void f(int n, int * restrict p, int * restrict q)

 {

while (n-- > 0)

*p++ = *q++;

}

関数の実行中に,一方のポインタ仮引数でアクセスするオブジェクトに他方のポインタ仮引数

ではアクセスしないことを明示する。

restrict

修飾子を使うと,処理系はプログラム中での関数 f の呼出しを検査せずに f での

実際の依存関係を解析できる。その代わり,f の呼出しがすべて未定義の動作を引き起こさな

いことを,プログラマが保証しなければならない。例えば,次の関数 g での 2 番目の f の呼出

しは,d[1]から d[49]までに p と q の両方からアクセスすることになるため,未定義の動作

を引き起こす。

void g(void)

 {

extern int d[100];

f(50, d + 50, d);

//

正しい

f(50, d +  1, d);

//

未定義の動作

}

3.  次の関数仮引数宣言は,

void h(int n, int * restrict p, int * restrict q, int * restrict r)

 {

   int

i;

for (i = 0; i < n; i++)

p[i] = q[i] + r[i];

}

オブジェクトを変更しなければ二つの restrict 修飾されたポインタが同じオブジェクトに別名で

アクセスできることを示す。特に a と b が記憶域の重ならない配列の場合,h(100, a, b, b)

という形式で関数 h を呼び出しても,関数 h 内では配列 b が変更されないため定義された動作

となる。

4. restrict ポインタ同士での代入を制限する規定は,関数呼出しと,それと同等な入れ子のブロッ

クとを区別しない。一つの例外を除いて,入れ子のブロックで宣言された restrict 修飾されたポ

インタの間で定義された動作をもつものは,

“外側から内側への”代入だけである。

 {


83

X 3010

:2003 (ISO/IEC 9899:1999)

     

int * restrict p1;

int * restrict q1;

p1 = q1; //

未定義の動作

   {

int * restrict p2 = p1;

//

正しい

int * restrict q2 = q1;

//

正しい

  p1

=

q2;

  //

未定義の動作

  p2

=

q2;

  //

未定義の動作

   }

}

この例外とは,restrict 修飾されたポインタ(より正確には,ポインタを示す通常の識別子)

が宣言されたブロックの実行が終了した場合,その値をそのブロックの外側で使うことができ

ることである。例えば,次の new_vector は vector を返却することができる。

typedef struct { int n; float * restrict v; } vector;

vector new_vector(int n)

 {

   vector

t;

t.n = n;

t.v = malloc(n * sizeof (float));

   return

t;

}

6.7.4

関数指定子

構文規則

関数指定子:

                                inline

制約  関数指定子は,識別子の関数としての宣言だけで使用できる。

外部結合をもつ関数のインライン定義が,静的記憶域期間をもつ変更可能なオブジェクトの定義を含ん

でいてはならず,内部結合をもつ識別子への参照も含んでいてはならない。

ホスト環境においては,inline 関数指定子を main の宣言に使ってはならない。

意味規則  inline 関数指定子で宣言された関数は,インライン関数(inline function)とする。この関数

指定子は複数回出現してもよいが,1 回だけ出現したときと同じ動作とする。関数をインライン関数にす

ることは,その関数の呼出しを可能な限り速くすることを示唆する(

118

)

。この示唆が効果をもつ程度は,

───────────────────────────────────────────────

(118)

例えば,通常の関数呼出し機構に対する代替として,

“インライン置換”を使う。インライン置換

は,テキスト上の置き換えではないし,新しい関数を作成することもない。そのため,例えば,そ

の関数本体内で使われるマクロの展開は,関数本体が出現する時点で行い,関数が呼び出される時

点では行わない。そして関数本体の位置で有効範囲にある宣言を識別子が参照する。また,外部定

義以外に行われるインライン定義の個数が幾つであれ,関数は単一のアドレスしかもたない。


84

X 3010

:2003 (ISO/IEC 9899:1999)

     

処理系定義とする(

119

)

内部結合をもつ任意の関数をインライン関数にすることができる。外部結合をもつ関数については次の

制限を適用する。関数を inline 関数指定子で宣言する場合,その関数を同じ翻訳単位内で定義しなけれ

ばならない。一つの翻訳単位内で一つの関数に対するすべてのファイル有効範囲の宣言が extern なしで

inline

関数指定子を含む場合,その翻訳単位内での定義を

インライン定義(inline definition)という。イ

ンライン定義はその関数に対する外部定義を与えず,他の翻訳単位での外部定義も禁止しない。インライ

ン定義は外部定義の代替を与える。処理系はこの代替を,同じ翻訳単位内でのその関数に対する呼出しの

実現に使用することができる。その関数の呼出しでインライン定義を使うか,外部定義を使うかは未規定

とする(

120

)

例  外部結合をもつインライン関数を宣言すると,外部定義か,又はその翻訳単位内だけで利用でき

る定義のいずれかを得ることができる。extern 付きのファイル有効範囲の宣言は外部定義を生

成する。次の例は一つの翻訳単位全体を示す。

inline double fahr(double t)

  {

return (9.0 * t) / 5.0 + 32.0;

  }

inline double cels(double t)

  {

return (5.0 * (t - 32.0)) / 9.0;

  }

extern double fahr(double);

//

外部定義を生成する

double convert(int is_fahr, double temp)

  {

   /*

処理系はインライン置換をしてもよい */

return is_fahr ? cels(temp) : fahr(temp);

}

fahr

は extern 付きでも宣言されているため fahr の定義は外部定義となるが,cels の定義

はインライン定義であることに注意する。cels は外部結合をもち cels への参照も存在するた

め,他の翻訳単位に cels の外部定義が存在しなければならない(6.9 参照)

。インライン定義と

外部定義は異なるものであり,その関数の呼出しを実現するのにいずれを使ってもよい。

前方参照    関数定義(6.9.1

───────────────────────────────────────────────

(119)

例えば,処理系がインライン置換を一切しなくてもよいし,インライン宣言の有効範囲内の呼出し

だけをインライン置換してもよい。

(120)

インライン定義は,それに対応する外部定義とは異なり,他の翻訳単位中の対応するインライン定

義とも異なるため,静的記憶域期間をもつすべての対応するオブジェクトも各定義ごとに異なる。


85

X 3010

:2003 (ISO/IEC 9899:1999)

     

6.7.5

宣言子

構文規則

宣言子:

ポインタ

opt

直接宣言子

直接宣言子:

識別子

                                (

宣言子    )

直接宣言子  [    型修飾子並び

opt

代入式

opt

    ]

直接宣言子  [    static  型修飾子並び

opt

代入式    ]

直接宣言子  [    型修飾子並び  static  代入式    ]

直接宣言子  [    型修飾子並び

opt

    *    ]

直接宣言子  (    仮引数型並び    )

直接宣言子  (    識別子並び

opt

    )

ポインタ:

                                *

型修飾子並び

opt

                                *

型修飾子並び

opt

ポインタ

型修飾子並び:

型修飾子

型修飾子並び    型修飾子

仮引数型並び:

仮引数並び

仮引数並び    ,  ...

仮引数並び:

仮引数宣言

仮引数並び    ,    仮引数宣言

仮引数宣言:

宣言指定子列    宣言子

宣言指定子列    抽象宣言子

opt

識別子並び:

識別子

識別子並び    ,    識別子

意味規則  各宣言子は一つの識別子を宣言する。式の中にその宣言子と同じ形式のオペランドが現れた場

合,そのオペランドは,宣言指定子列が指示する有効範囲,記憶域期間及び型をもつ関数又はオブジェク

トを指し示す。

他の宣言子の一部ではない宣言子を

完結宣言子(full declarator)と呼ぶ。完結宣言子の最後は副作用完

了点とする。完結宣言子の中に入れ子になった宣言子の並びが可変長配列型を含む場合,完結宣言子で指

定する型を

可変修飾(variably modified)であるという。

6.7.5

6.7.5.3 では次の宣言を考える。


86

X 3010

:2003 (ISO/IEC 9899:1999)

     

                T    D1

ここで T は,型

T

(例えば int)を指定する宣言指定子列とする。D1 は宣言子とし,D1 に含まれる識別

子をここでは

ident

と呼ぶ。宣言子の各形式では,識別子

ident

に対して指定する型をこの記法を用いて帰

納的に説明する。

宣言“T D1”において D1 が形式

識別子

をもつ場合,

ident

の型は

T

とする。

宣言“T D1”において D1 が形式

                ( D )

をもつ場合,

ident

は宣言“T D”によって指定される型をもつ。すなわち括弧内の宣言子は,括弧なしの

宣言子と同一となるが,複雑な宣言子の結合が括弧によって変更されることがある。

処理系限界  5.2.4.1 の規定に従い,処理系は算術型,構造体型,共用体型又は不完全型を直接的に又は一

つ以上の typedef を介して間接的に修飾するポインタ,

配列及び関数の宣言子の個数を制限してもよい。

前方参照    型定義(6.7.7),配列宣言子(6.7.5.2

6.7.5.1

ポインタ宣言子

意味規則

宣言“T D1”において,D1 が形式

                *

型修飾子並び

opt

    D

をもつ場合,次のとおりとする。宣言“T D”の

ident

に対して指定される型が“

T

の派生宣言子型並び”

であれば,

“T D1”の

ident

に対して指定される型は“

T

への型修飾子並びをもつポインタの派生宣言子型

並び”とする。

ident

は,並びの中の各型修飾子によって修飾されたポインタとなる。

二つのポインタ型が適合するためには,いずれも同一の修飾がなされていなければならず,かつ両者が

適合する型へのポインタでなければならない。

例  次の二つの宣言は,“不変値への可変ポインタ”と“可変値への不変ポインタ”の違いを示す。

const int *ptr_to_constant;

int *const constant_ptr;

ptr_to_constant

の指すオブジェクトの内容は,そのポインタを通して変更してはならないが,

ptr_to_constant

自 身 は 他 の オ ブ ジ ェ ク ト を 指 す よ う 変 更 し て も よ い 。 同 様 に ,

constant_ptr

によって指される int の内容は変更してもよいが,constant_ptr 自身は常に

同一の位置を指さなければならない。

不変ポインタ constant_ptr の宣言は,型“int へのポインタ”の定義を含めることで分か

りやすくできる。

typedef int *int_ptr;

const int_ptr constant_ptr;

は,型“int への const 修飾したポインタ”をもつオブジェクトとして constant_ptr を宣言す

る。

6.7.5.2

配列宣言子

制約  [及び]の間には,省略可能な型修飾子及びキーワード static に加え,式又は*を置くことができ

る。[及び]が(配列の大きさを指定する)式を囲む場合,その式の型は整数型でなければならない。式が

定数式の場合,その値は 0 より大きくなければならない。要素の型が不完全型又は関数型であってはなら


87

X 3010

:2003 (ISO/IEC 9899:1999)

     

ない。省略可能な型修飾子及びキーワード static は,配列型をもつ関数仮引数の宣言中だけで使用でき

る。そして,一番外側の配列型派生だけで使用できる。

通常の識別子(6.2.3 で定義する)のうち,ブロック有効範囲又は関数原型有効範囲をもち無結合である

ものだけが可変修飾型をもつことができる。識別子が静的記憶域期間をもつオブジェクトと宣言される場

合,その型を可変長配列型にすることはできない。

意味規則  宣言“T D1”において D1 が

                D [

型修飾子並び

opt

代入式

opt

      ]

                D  [  static

型修飾子並び

opt

代入式    ]

                D [

型修飾子並び

opt

    static

代入式    ]

                D [

型修飾子並び

opt

    *  ]

のいずれかの形式をもつ場合,次のとおりとする。宣言“T D”の

ident

に対して指定される型が“

T

の派

生宣言子型並び”であれば,

“T D1”の

ident

に対して指定される型は“

T

の配列の派生宣言子型並び”と

する(

121

)

(省略可能な型修飾子とキーワード static については 6.7.5.3 を参照。

大きさの指定がない場合,その配列型は不完全型とする。大きさが式ではなく*で指定された場合,そ

の配列型は大きさの指定がない可変長配列型とする。この型は,完全型とするが,関数原型有効範囲をも

つ宣言の中でだけ使用できる(

122

)

。大きさが整数定数式で要素の型が既知で一定の大きさをもつ場合,そ

の配列型は非可変長配列型とする。そうでない場合,その配列型を可変長配列型とする。

大きさが整数定数式以外の式である場合,

次のとおりとする。

その宣言が関数原型有効範囲にある場合,

式を*で置き換えた場合と同じ規則で扱う。そうでない場合,式を評価した値は,常に 0 より大きくなけ

ればならない。可変長配列型の各実体の大きさは,その生存期間の間変わることがない。大きさを示す式

が sizeof 演算子のオペランドの一部で,その式の値を変更しても演算子の結果に影響を与えない場合,

その式を評価するかどうかは未規定とする。

二つの配列型が適合するためには,まず,両者が適合する要素型をもたなければならない。さらに,両

者が配列の大きさを指定する整数定数式をもつ場合,それらの値は同じ定数値でなければならない。二つ

の配列型が適合することを必要とする文脈で使われ,両者の大きさ指定子を評価した値が異なる場合,そ

の動作は未定義とする。

1.

float fa[11], *afp[17];

は,float 型の配列と float 型へのポインタの配列を宣言する。

2.  次の宣言の違いに注意しなければならない。

extern int *x;

extern int y[];

1

番目は,x を int 型へのポインタと宣言する。2 番目は,y を記憶域がどこかで定義される,

大きさの指定されない int の配列(不完全型)と宣言する。

3.  次の宣言は,幾つかの可変修飾型に関する適合規則を示す。

extern int n;

───────────────────────────────────────────────

(121)

幾つかの“∼の配列”の指定を連続的に並べることによって,多次元配列を宣言できる。

(122)

すなわち,*は定義でない関数宣言(6.7.5.3 参照)の中だけで使用することができる。


88

X 3010

:2003 (ISO/IEC 9899:1999)

     

extern int m;

 void

fcompat(void)

 {

   int

a[n][6][m];

   int

(*p)[4][n+1];

   int

c[n][n][6][m];

   int

(*r)[n][n][n+1];

p = a;

//

正しくない: 4 != 6 であるため適合していない

r = c;

//

適合するが,n == 6 でかつ m == n+1 の場合だけ

   //

動作が定義される

}

4.  可変修飾(VM)型のすべての宣言は,ブロック有効範囲又は関数原型有効範囲をもたなけれ

ばならない。static 又は extern 記憶域クラス指定子で宣言される配列オブジェクトは,可

変長配列(VLA)型をもてない。しかし,static 記憶域クラス指定子で宣言されるオブジェ

クトが VM 型(すなわち,VLA 型へのポインタ)をもつこともできる。さらに,VM 型で宣言

されるすべての識別子は,通常の識別子でなければならないので,構造体又は共用体のメンバ

にはなれない。

extern int n;

int A[n];

//

正しくない:VLA がファイル有効範囲にある

extern int (*p2)[n];

//

正しくない:VM がファイル有効範囲にある

int B[100];

//

正しい:B はファイル有効範囲にあるが VM ではない

void fvla(int m, int C[m][m]); //

正しい:VLA が関数原型有効範囲にある

void fvla(int m, int C[m][m])   //

正しい:VLA への auto ポインタに型調整される

{

typedef  int  VLA[m][m];    //

正しい:VLA がブロック有効範囲にある

struct tag {

int  (*y)[n];       //

正しくない:y が通常の識別子でない

int  z[n];

     //

正しくない:z が通常の識別子でない

 };

int  D[m];

     //

正しい:auto の VLA

static  int  E[m];

     //

正しくない:VLA がブロック有効範囲の static

extern  int  F[m];

     //

正しくない:F が結合をもっているのに VLA

int  (*s)[m];

     //

正しい:VLA への auto ポインタ

extern int (*r)[m];

//

正しくない:r が結合をもっているのに VLA へのポインタ

static int (*q)[m] = &B;

//

正しい:q は VLA へのポインタでブロック有効範囲の static

}

前方参照  関数宣言子(6.7.5.3),関数定義(6.9.1),初期化(6.7.8


89

X 3010

:2003 (ISO/IEC 9899:1999)

     

6.7.5.3

関数宣言子(関数原型を含む)

制約  関数宣言子は,関数型又は配列型を返却値の型として指定してはならない。

仮引数宣言に記憶域クラス指定子として,register 以外のものを指定してはならない。

関数定義の一部でない関数宣言子における識別子並びは,空でなければならない。

関数定義の一部である関数宣言子の仮引数型並びにある仮引数は,型調整後に不完全型をもってはなら

ない。

意味規則  宣言“T D1”において D1 が形式

                D (

仮引数型並び  )

又は

                D (

識別子並び

opt

 )

をもつ場合,次のとおりとする。宣言“T D”の

ident

に対して指定される型が“

T

の派生宣言子型並び”

であれば,

“T D1”の

ident

に対して指定される型は“

T

を返す関数の派生宣言子型並び”とする。

仮引数型並びは,関数の仮引数の型を指定する。仮引数の識別子を宣言してもよい。

仮引数を“∼型の配列”とする宣言は,

“∼型への修飾されたポインタ”に型調整する。そのときの型修

飾子は,配列型派生の[及び]の間で指定したものとする。配列型派生の[及び]の間にキーワード static

がある場合,その関数の呼出しの際に対応する実引数の値は,大きさを指定する式で指定される数以上の

要素をもつ配列の先頭要素を指していなければならない。

仮引数を“∼型を返却する関数”とする宣言は,6.3.2.1 の規定に従い,

“∼型を返却する関数へのポイン

タ”に型調整する。

並びの最後が省略記号(, ...)の場合,そのコンマ以降の実引数の個数及び型に関する情報はない(

123

)

並びの中の唯一の項目が void 型で名前のない仮引数であるという特別な場合,関数が仮引数をもたな

いことを指定する。

仮引数宣言内では,括弧で囲まれた単一の型定義名は,単一の仮引数をもつ関数を指定する抽象宣言子

と解釈する。宣言子の識別子を囲む冗長な括弧とは解釈しない。

関数宣言子が関数定義の一部ではない場合,仮引数の型は不完全型でもよく,また宣言指定子列に[*]

を使って可変長配列型を指定してもよい。

仮引数宣言の宣言指定子列に記憶域クラス指定子がある場合,その仮引数宣言が関数定義の仮引数型並

びの中にあるのでなければ記憶域クラス指定子を無視する。

識別子並びは,関数の仮引数の識別子だけを宣言する。関数定義の一部である関数宣言子で識別子並び

が空の場合,関数が仮引数をもたないことを指定する。関数定義の一部でない関数宣言子の識別子並びが

空の場合,仮引数の個数及び型の情報がないことを指定する(

124

)

二つの関数型が適合するためには,次の条件をすべて満たさなければならない。

−  両方が適合する返却値の型をもつ(

125

)

−  両方が仮引数型並びをもつ場合,仮引数の個数及び省略記号の有無に関して一致し,対応する仮引数

───────────────────────────────────────────────

(123)

<stdarg.h>

ヘッダ(7.15 参照)で定義されるマクロを使えば,省略記号に対応する引数へのアク

セスが可能となる。

(124)

“今後の言語の方針”

6.11.6 参照)

(125)

両方の関数型が“古い形式”の場合,仮引数の型は比較されない。


90

X 3010

:2003 (ISO/IEC 9899:1999)

     

の型が適合する。

−  一方の型が仮引数型並びをもち,他方の型が関数定義の一部でない関数宣言子によって指定され,識

別子並びが空の場合,仮引数型並びは省略記号を含まない。各仮引数の型は,既定の実引数拡張を適

用した結果の型と適合する。

−  一方の型が仮引数型並びをもち,他方の型が関数定義によって指定され,識別子並び(空でもよい)

をもつ場合,両方の仮引数の個数は一致する。さらに関数原型のほうの各仮引数の型は,対応する識

別子の型に既定の実引数拡張を適用した結果の型と適合する。

(型の適合及び型の合成を判断すると

き,関数型又は配列型で宣言される各仮引数は型調整後の型をもつものとして扱い,修飾型で宣言さ

れる各仮引数は宣言された型の非修飾版をもつものとして扱う。

1.  宣言

int f(void), *fip(), (*pfi)();

は,

−  仮引数をもたず int を返す関数 f

−  仮引数の情報をもたず int へのポインタを返す関数 fip

−  仮引数の情報をもたず int を返す関数へのポインタ pfi

を宣言する。特に後者二つの比較が有用である。*fip()の結合は*(fip())となるので,宣言

は,まず関数 fip を呼び出し,次にポインタによる間接を使って int を得ることを示す。こ

れは式の場合も同様である。宣言子(*pfi)()では,まず関数へのポインタに対する間接演算

が関数指示子を生じる。次にそれが関数の呼出しに用いられ,その関数は int を返す。このこ

とを指示するために,括弧は省略できない。

宣言が関数の外にある場合,これらの識別子はファイル有効範囲及び外部結合をもつ。宣言

が関数の中にある場合,関数の識別子 f 及び fip は,ブロック有効範囲及び(これらの識別子

に対するファイル有効範囲の可視な宣言が何であるかに依存して)内部結合又は外部結合をも

つ。この場合,ポインタの識別子 pfi は,ブロック有効範囲及び無結合をもつ。

2.  宣言

int (*apfi[3])(int *x, int *y);

は,int を返す関数へのポインタ 3 個から成る配列 apfi を宣言する。これらの関数は,仮引

数として int へのポインタを 2 個もつ。識別子 x 及び y の宣言は,説明のための意味しかもた

ず,apfi の宣言の終わりでその有効範囲は終わる。

3.  宣言

int (*fpfi(int (*)(long), int))(int, ...);

は,関数 fpfi を宣言する。関数 fpfi は,int を返す関数へのポインタを返す。fpfi は,二

つの仮引数をもつ。それらの仮引数の一つは int を返す関数(long int 型の仮引数を 1 個

もつ。

)へのポインタ,もう一つは int である。fpfi が返すポインタが指す関数は,一つの

int

型の仮引数をもち,更に 0 個以上の任意の型の付加的な実引数を受け取る。

4.  次の関数原型は可変修飾型の仮引数をもつ。

void addscalar(int n, int m,

double a[n][n*m+300], double x);

 int

main()


91

X 3010

:2003 (ISO/IEC 9899:1999)

     

 {

   double

b[4][308];

addscalar(4, 2, b, 2.17);

   return

0;

 }

void addscalar(int n, int m,

double a[n][n*m+300], double x)

 {

for (int i = 0; i < n; i++)

for (int j = 0, k = n*m+300; j < k; j++)

   //

a

は n*m+300 個の要素をもつ VLA へのポインタ

   a[i][j]

+=

x;

}

5.  次はすべて適合する関数原型を宣言する。

double maximum(int n, int m, double a[n][m]);

double maximum(int n, int m, double a[*][*]);

double maximum(int n, int m, double a[ ][*]);

double maximum(int n, int m, double a[ ][m]);

次も同様である。

void f(double (* restrict a)[5]);

void f(double a[restrict][5]);

void f(double a[restrict 3][5]);

void f(double a[restrict static 3][5]);

(最後の宣言は,f を呼び出すときには,a に対応する実引数が,5 個の double から成る配

列要素を 3 個以上もつ配列の先頭を指す空でないポインタでなければならないことも指定して

いることに注意しなければならない。他の宣言は,そのような指定をしない。

前方参照  型名(6.7.6),関数定義(6.9.1

6.7.6

型名

構文規則

型名:

型指定子型修飾子並び    抽象宣言子

opt

抽象宣言子:

ポインタ

ポインタ

opt

直接抽象宣言子

直接抽象宣言子:

                                (

抽象宣言子    )

直接抽象宣言子

opt

    [

代入式

opt

    ]

直接抽象宣言子

opt

    [ * ]


92

X 3010

:2003 (ISO/IEC 9899:1999)

     

直接抽象宣言子

opt

    (

仮引数型並び

opt

    )

意味規則  幾つかの文脈では,型を指定することが必要となる。型の指定は,型名(type name)を使って

行う。型名は,構文的にはその型の関数又はオブジェクトの宣言から識別子を取り去った形に相当する(

126

)

例  プログラム片

(a)

int

(b)

int *

(c)

int *[3]

(d)

int (*)[3]

(e)

int (*)[*]

(f)

int *()

(g)

int (*)(void)

(h)

int (*const [])(unsigned int, ...)

は,それぞれ次の型を指定する。

(a)  int

(b)  int

へのポインタ

(c)  int

へのポインタ 3 個から成る配列

(d) 3

個の int から成る配列へのポインタ

(e)

個数が指定されない int の可変長配列へのポインタ

(f)

仮引数に関する情報をもたず int へのポインタを返す関数

(g)

仮引数をもたず int を返す関数へのポインタ

(h)

関数への不変ポインタの,個数が未指定の配列。各関数は unsigned int 型の一つの仮引

数及び個数が未指定の他の仮引数をもち,int を返す。

6.7.7

型定義

構文規則

型定義名:

識別子

制約  可変修飾型を指定する型定義名は,ブロック有効範囲をもたなければならない。

意味規則  記憶域クラス指定子が typedef の宣言では,各宣言子は識別子を型定義名として定義する。

型定義名は,その識別子に対して指定した型を表す(6.7.5 で規定する。

。可変長配列宣言子で使われる配

列の大きさを示す式は,型定義名の宣言に到達するたびに評価する。typedef 宣言は,新しい型を導入す

るのではなく,指定した型の同義語だけを導入する。すなわち,次の宣言

                              typedef T type_ident;

               type_ident  D;

において,type_ident を,宣言指定子列 T(この型を

T

とする。

)によって指定した型をもつ型定義名

として定義する。D の中の識別子は,型“

T

の派生宣言子型並び”をもつ。ここで,派生宣言子型並びは,

D

の宣言子で指定したものとする。型定義名は,通常の宣言子で宣言した他の識別子と同じ名前空間を共

───────────────────────────────────────────────

(126)

構文が示すとおり,型名の中の空の括弧は,仮引数に関する情報をもたない関数として解釈する。

省略された識別子のまわりの冗長な括弧とは解釈しない。


93

X 3010

:2003 (ISO/IEC 9899:1999)

     

有する。

1.

typedef int MILES, KLICKSP();

typedef struct { double hi, lo; } range;

の後では,プログラム片

MILES distance;

extern KLICKSP *metricp;

 range

x;

range z, *zp;

は,すべて正しい宣言である。distance の型は int,metricp の型は“仮引数に関する情

報をもたず int を返す関数へのポインタ”

,x 及び z の型は前に宣言した構造体,zp は同じ構

造体へのポインタである。オブジェクト distance は,任意の int オブジェクトと適合する

型をもつ。

2.  宣言

typedef struct s1 { int x; } t1, *tp1;

typedef struct s2 { int x; } t2, *tp2;

の後では,型 t1 と tp1 の指す型とは適合する。型 t1 は,型 struct s1 と適合する。しか

し,型 struct s2,型 t2,tp2 の指す型及び型 int とは適合しない。

3.  次の,分かりにくいプログラム片

typedef signed int t;

typedef int plain;

struct tag {

   unsigned

t:4;

   const

t:5;

   plain

r:5;

 };

では,

型定義名 t を型 signed int として,

型定義名 plain を型 int としてそれぞれ宣言    し,

更に三つのビットフィールドメンバをもつ構造体を宣言している。ビットフィールドメンバは

それぞれ,

−  名前が t で,[0,15]の範囲の値をとるもの

−  名前がなく(もしアクセスできたとすれば)[

15,+15]

又は[

16,+15]

の範囲の値をとる const

修飾されたもの(範囲の選択は処理系定義)

−  名前が r で,[0,31],[

15,+15]

又は[

16,+15]

の範囲の値をとるもの(範囲の選択は処理系

定義)

となる。1 番目と 2 番目の違いは,1 番目のビットフィールド宣言では unsigned が型指定子

である(このため t は構造体メンバの名前となる。

)のに対し,2 番目のビットフィールド宣言

では const が型修飾子である(これは型定義名としてこの場所で依然として可視な t を修飾

する。

)ことである。この宣言の後で,内側の有効範囲で

t f(t (t));

   long

t;


94

X 3010

:2003 (ISO/IEC 9899:1999)

     

とした場合,関数 f を型“名前のない仮引数を一つもち,signed int を返す関数”として

宣言する。f の仮引数は,名前のない signed int 型の仮引数を一つもち,signed int を

返す関数へのポインタ型である。識別子 t は型 long int をもつ。

4.  一方,型定義名は,プログラムを読みやすくするために使用できる。次の三つの signal 関数

の宣言は,完全に同じ型を指定している。ここで 1 番目の例は,型定義名を使用せずに型を指

定している。

typedef void fv(int), (*pfv)(int);

void (*signal(int, void (*)(int)))(int);

fv *signal(int, fv *);

pfv signal(int, pfv);

5.  型定義名が可変長配列型を表す場合,型定義名が使われるたびではなく,その定義の時に配列

長を固定する。

void copyt(int n)

 {

typedef int B[n];

// B

は n 個の int,n はここで評価される

n += 1;

 B

a;

 //

a

は n(+=1 適用前の n)個の int

int b[n];

// a

と b は異なる大きさ

for (int i = 1; i < n; i++)

a[i-1] = b[i];

}

6.7.8

初期化

構文規則

初期化子:

代入式

                                {

初期化子並び    }

                                {

初期化子並び    ,    }

初期化子並び:

指示

opt

初期化子

初期化子並び    ,    指示

opt

初期化子

指示:

要素指示子並び  =

要素指示子並び:

要素指示子

要素指示子並び  要素指示子

要素指示子:

                                [

定数式  ]

                                .

識別子

制約  初期化する実体に含まれないオブジェクトに初期化子で値を格納してはならない。


95

X 3010

:2003 (ISO/IEC 9899:1999)

     

初期化する実体の型は,大きさの分からない配列型であるか,又は可変長配列型以外のオブジェクト型

でなければならない。

静的記憶域期間をもつオブジェクトの初期化子の中のすべての式は定数式又は文字列リテラルでなけれ

ばならない。

識別子の宣言がブロック有効範囲をもち,かつ識別子が外部結合又は内部結合をもつ場合,その宣言に

その識別子に対する初期化子があってはならない。

要素指示子が

                              [

定数式  ]

という形式の場合,現オブジェクト(この箇条で定義する。

)は配列型をもち,式は整数定数式でなければ

ならない。配列の大きさが分からない場合,式の値は任意の非負数であってよい。

要素指示子が

                              .

識別子

という形式の場合,現オブジェクト(この箇条で定義する。

)は構造体型又は共用体型をもち,識別子はそ

の型のメンバ名でなければならない。

意味規則  初期化子は,オブジェクトに格納する初期値を指定する。

この規格で明示的に異なる規定を行わない限り,この箇条では構造体型又は共用体型のオブジェクトの

名前のないメンバを初期化の対象とはしない。構造体オブジェクトの名前のないメンバは,初期化後であ

っても不定の値をもつ。

自動記憶域期間をもつオブジェクトを明示的に初期化しない場合,その値は不定とする。静的記憶域期

間をもつオブジェクトを明示的に初期化しない場合,次の規定に従う。

a

)

そのオブジェクトの型がポインタ型の場合,空ポインタに初期化する。

b

)

そのオブジェクトの型が算術型の場合,

(正又は符号無しの)0 に初期化する。

c

)

そのオブジェクトが集成体の場合,各メンバに a)∼d)の規定を(再帰的に)適用し初期化する。

d

)

そのオブジェクトが共用体の場合,最初の名前付きメンバに a)∼d)の規定を(再帰的に)適用し初

期化する。

スカラオブジェクトに対する初期化子は,

単一の式でなければならない。

それを波括弧で囲んでもよい。

そのオブジェクトの初期値は(型変換後の)その式の値とする。型の制限及び型変換は,単純代入と同じ

とする。このとき,宣言した型の非修飾版を,スカラオブジェクトの型とみなす。

この箇条のこれ以降では,集成体型又は共用体型のオブジェクトの初期化子を扱う。

自動記憶域期間をもつ構造体オブジェクト又は共用体オブジェクトに対する初期化子は,この箇条で規

定する初期化子並び,

又は適合する構造体型若しくは共用体型の単一の式のいずれかでなければならない。

後者の場合,名前のないメンバも含めて,その式の値を,そのオブジェクトの初期値とする。

文字型の配列は,単純文字列リテラルで初期化してもよい。それを波括弧で囲んでもよい。単純文字列

リテラルの文字(空きがある場合又は配列の大きさが分からない場合,終端ナル文字も含めて。

)がその配

列の要素を前から順に初期化する。

wchar_t

型と適合する要素型の配列は,ワイド文字列リテラルで初期化してもよい。それを波括弧で囲

んでもよい。ワイド文字列リテラルのワイド文字(空きがある場合又は配列の大きさが分からない場合,

終端ナルワイド文字も含めて。

)がその配列の要素を前から順に初期化する。

これら以外の場合,集成体型又は共用体型をもつオブジェクトに対する初期化子は,要素又は名前付き

メンバに対する初期化子並びを波括弧で囲んだものでなければならない。


96

X 3010

:2003 (ISO/IEC 9899:1999)

     

波括弧で囲まれたそれぞれの初期化子並びに結び付くオブジェクトを,

現オブジェクト(current object)

という。指示がない場合,現オブジェクト中の部分オブジェクトを,現オブジェクトの型に従う順序で初

期化する。すなわち,配列要素は添字の昇順で初期化し,構造体メンバは宣言の順で初期化し,共用体で

は最初の名前付きメンバを初期化する(

127

)

。一方,指示が存在する場合,それに続く初期化子を使って要

素指示子が示す部分オブジェクトを初期化する。そして要素指示子で示される部分オブジェクトの次の部

分オブジェクトから順に初期化を続ける(

128

)

各要素指示子並びは,それを囲む最も近い波括弧の対に結び付けられた現オブジェクトに対する記述で

メンバを指定する。要素指示子並びの各項目は(順に)現オブジェクトの特定のメンバを指定し,次の要

素指示子があれば現オブジェクトをそのメンバに変更する(

129

)

。一つの要素指示子並びを処理した後の現

オブジェクトは,続く初期化子で初期化される部分オブジェクトとする。

初期化は,初期化子並びの順に行う。特定の部分オブジェクトに対する初期化子が,同じ部分オブジェ

クト(

129a

)

に対する以前の初期化子を書き換えることもある。明示的に初期化されないすべての部分オブジ

ェクトについては,静的記憶域期間をもつオブジェクトと同じ規則で暗黙に初期化する。

集成体又は共用体が集成体又は共用体の要素又はメンバを含む場合,これらの規則をその部分集成体又

は含まれる共用体に再帰的に適用する。部分集成体又は含まれる共用体の初期化子が左波括弧で始まる場

合,その波括弧と対応する右波括弧で囲まれた初期化子は,その部分集成体又は含まれる共用体の要素又

はメンバを初期化する。そうでない場合,部分集成体の要素若しくはメンバ又は含まれる共用体の最初の

メンバに見合うに十分なだけ並びから初期化子が取られる。残りの初期化子は,その部分集成体又は含ま

れる共用体の外側の集成体の次の要素又はメンバの初期化のために残す。

集成体型の要素又はメンバの個数より波括弧で囲まれた並びにある初期化子が少ない場合,又は大きさ

が既知の配列の要素数よりその配列を初期化するための文字列リテラル中の文字数が少ない場合,その集

成体型の残りを,静的記憶域期間をもつオブジェクトと同じ規則で暗黙に初期化する。

大きさの分からない配列を初期化する場合,明示的な初期化子をもつ要素の添字の最大値でその大きさ

を決定する。初期化子並びの終了時点で,その配列はもはや不完全型をもたない。

初期化子並びの式中で副作用の発生する順序は,未規定とする(

130

)

1.  <complex.h>が#include されているとき,宣言

int i = 3.5;

complex c = 5 + 3 * I;

───────────────────────────────────────────────

(127)

部分集成体又は含まれる共用体に対する初期化子並びが左波括弧で始まらない場合,それらの部分

オブジェクトを通常の方法で初期化するが,部分集成体又は含まれる共用体が現オブジェクトにな

ることはない。現オブジェクトは,波括弧で囲まれた初期化子並びにだけ結び付く。

(128)

共用体の一つのメンバが初期化された後の次のオブジェクトは,共用体の次のメンバではない。共

用体を含むオブジェクト内の次の部分オブジェクトが次のオブジェクトとなる。

(129)

すなわち,波括弧の対に結び付けられた集成体又は共用体の直接の部分オブジェクトを指定するた

めだけに要素指示子を使うことができる。さらに,個々の要素指示子並びは独立である。

(129a)

部分オブジェクトに対する初期化子が書き換えられて,その部分オブジェクトの初期化に使われな

い場合,その初期化子は全く評価しなくてもよい。

(130)

特に,評価の順序が部分オブジェクトを初期化する順序と同じである必要はない。


97

X 3010

:2003 (ISO/IEC 9899:1999)

     

は,i を定義し値 3 で初期化する。さらに,c を定義し値 5.0+

i

3.0

で初期化する。

2.  宣言

int x[] = { 1, 3, 5 };

では,大きさが未指定であり,かつ初期化子が三つあるため,x を三つの要素をもつ 1 次元配

列のオブジェクトとして定義し,初期化する。

3.  宣言

int y[4][3] = {

{ 1, 3, 5 },

{ 2, 4, 6 },

{ 3, 5, 7 },

 };

は,完全に波括弧で囲まれた初期化をもつ定義である。1,3 及び 5 は,y の第 1 行(配列オブ

ジェクト y[0])すなわち y[0][0],y[0][1]及び y[0][2]を初期化する。同様に,次の 2

行は,y[1]及び y[2]を初期化する。初期化子の個数が要素数より少ないので,y[3]の各要素

の初期値は 0 となる。

int y[4][3] = {

1, 3, 5, 2, 4, 6, 3, 5, 7

 };

によっても完全に同じ結果を得る。y[0]の初期化子は,左波括弧で始まらないため並びの中か

ら三つの要素を使う。同様に y[1]及び y[2]に次の三つずつを引き続いて使う。

4.  宣言

int z[4][3] = {

{ 1 }, { 2 }, { 3 }, { 4 }

 };

は,z の第 1 列を指定されたように初期化し,残りを 0 で初期化する。

5.  宣言

struct { int a[3], b; } w[] = { { 1 }, 2 };

は,波括弧による囲み方が不統一な初期化をもつ定義である。これは,二つの構造体型の要素

をもつ配列を定義する。w[0].a[0]は 1,w[1].a[0]は 2 となり,他の要素はすべて 0 とな

る。

6.  宣言

short q[4][3][2] = {

{ 1 },

{ 2, 3 },

{ 4, 5, 6 }

 };

は,不完全だが波括弧による囲み方が統一された初期化を含む。これは,3 次元配列オブジェ

クトを定義する。q[0][0][0]は 1,q[1][0][0]は 2,q[1][0][1]は 3 となり,更に 4,5

及び 6 は q[2][0][0],q[2][0][1]及び q[2][1][0]をそれぞれ初期化する。残りはすべて

0

となる。q[0][0]の初期化子は左波括弧で始まらないので,現在の並びの中から六つまでの


98

X 3010

:2003 (ISO/IEC 9899:1999)

     

要素を使うことができる。この場合は初期化子が一つだけなので,残りの五つの要素を 0 で初

期化する。同様に q[1][0]及び q[2][0]の初期化子は左波括弧で始まらないので,各々六つ

までの要素をそれぞれの 2 次元部分集成体を初期化するために使う。いずれかの並びの中に六

つを超える要素があった場合,診断メッセージが出力されるであろう。同様の初期化は,

short q[4][3][2] = {

1, 0, 0, 0, 0, 0,

2, 3, 0, 0, 0, 0,

4, 5, 6

 };

又は完全に波括弧で囲まれた形式

short q[4][3][2] = {

   {

{ 1 },

   },

   {

{ 2, 3 },

   },

   {

{ 4, 5 },

{ 6 },

   }

 };

によっても達成できる。

一般に,完全な括弧付けをした形式,又は最低限の括弧を使った形式が混乱を生じにくい。

7.  配列型を完全にする初期化の形式の一つは,型定義名を含む。宣言

typedef int A[];

//

OK

ブロック有効範囲をもつ宣言

が与えられた場合,宣言

A a = { 1, 2 }, b = { 3, 4, 5 };

は,不完全型の規則によって,

int a[] = { 1, 2 }, b[] = { 3, 4, 5 };

と同一となる。

8.  宣言

char s[] = "abc", t[3] = "abc";

は,要素を単純文字列リテラルで初期化された“単なる”char 型の配列オブジェクト s 及び t

を定義する。この宣言は,

char s[] = { 'a', 'b', 'c', '

\0' },

t[] = { 'a', 'b', 'c' };

と同一となる。配列の内容は,変更できる。一方,宣言

char *p = "abc";

は,p を“char へのポインタ”型として定義し,要素が単純文字列リテラルで初期化され,長


99

X 3010

:2003 (ISO/IEC 9899:1999)

     

さが 4 の“char の配列”型オブジェクトを指すように初期化する。p を用いてその配列の内容

を変更しようとした場合,その動作は未定義である。

9.  要素指示子を使うことにより,配列を列挙体の要素に対応するように初期化することができる。

enum { member_one, member_two };

const char *nm[] = {

[member_two] = "member two",

[member_one] = "member one",

 };

10.  構造体メンバの順序に依存せずにメンバを 0 以外の値に初期化することができる。

div_t answer = { .quot = 2, .rem = -1 };

11.  単純な初期化子が誤解されそうな場合,要素指示子を使って明示的な初期化をすることができ

る。

struct { int a[3], b; } w[] =

{ [0].a = {1}, [1].a[0] = 2 };

12.  要素指示子を一つだけ使うことで,配列の両端に初期値を与えることができる。

int a[MAX] = {

1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0

 };

この例において MAX が 10 より大きい場合,配列中央に幾つかの値 0 の要素が存在すること

になる。MAX が 10 よりも小さい場合,先頭の 5 個の初期化子で与えられた値の幾つかを後半

の 5 個の初期化子が書き換える。

13.  共用体の任意のメンバを初期化することができる。

union { /*

... */ } u = { .any_member = 42 };

前方参照  共通の定義<stddef.h>(7.17

6.8

文及びブロック

構文規則

文:

ラベル付き文

複合文

式文

選択文

繰返し文

分岐文

意味規則  文(statement)は,実行すべき動作を規定する。別に規定する場合を除き,文は順番に実行す

る。

ブロック(block)は,幾つかの宣言及び文を一つの構文的な単位にまとめることを可能にする。自動記

憶域期間をもつオブジェクトの初期化子,及びブロック有効範囲をもつ通常の識別子の可変長配列宣言子

は,文の場合と同じく実行中に宣言に到達するたびにこれを評価し,値をそのオブジェクトに格納する(初

期化子をもたないオブジェクトに不定の値を格納することを含む。

。一つの宣言の中の評価と格納の順序


100

X 3010

:2003 (ISO/IEC 9899:1999)

     

は,宣言子が現れる順とする。

完結式(full expression)は,他の式の部分にも宣言子の部分にもなっていない式とする。初期化子,式

文の中の式,選択文(if 文又は switch 文)の制御式,while 文又は do 文の制御式,for 文の(省略

可能な)各式,及び return 文の(省略可能な)式は完結式となる。完結式の終わりは,副作用完了点と

する。

前方参照  return 文(6.8.6.4),繰返し文(6.8.5),式文及び空文(6.8.3),選択文(6.8.4

6.8.1

ラベル付き文

構文規則

ラベル付き文:

識別子

:

                              case

定数式

:

                              default

:

制約  case ラベル又は default ラベルは,switch 文の中以外の場所に現れてはならない。これらのラ

ベルに対するその他の制約は,6.8.4.2 で規定する。

ラベル名は,関数の中で一意でなければならない。

意味規則  任意の文の前に,一つの識別子をラベル名として宣言する接頭語があってもよい。ラベル自体

は,制御の流れを変更しない。制御の流れは,ラベルに妨げられることなく続く。

前方参照  goto 文(6.8.6.1),switch 文(6.8.4.2

6.8.2

複合文

構文規則

複合文:

                              {

ブロック構成要素並び

opt

 }

ブロック構成要素並び:

ブロック構成要素

ブロック構成要素並び    ブロック構成要素

ブロック構成要素:

宣言

意味規則  複合文(compound statement)はブロックとする。

6.8.3

式文及び空文

構文規則

式文:

opt

    ;

意味規則  式文の中の式は,その副作用(

131

)

を発生させることを目的に,ボイド式として評価する。

空文(null statement)(セミコロンだけの文)は,何の動作も行わない。

1.  関数呼出しを副作用だけを目的とする式文として評価する場合,式をキャストでボイド式に型

───────────────────────────────────────────────

(131)

代入や副作用をもつ関数呼出しなど。


101

X 3010

:2003 (ISO/IEC 9899:1999)

     

変換することによって,その値を捨て去ることを明示できる。

int p(int);

 /*

... */

 (void)p(0);

2.  プログラム片

char *s;

 /*

... */

while(*s++ != '

\0')

;

では,繰返し文に空のループ本体を与えるために,空文を使用している。

3.  複合文を閉じる}の直前にラベルを置くために,空文を使用することもできる。

while(loop1) {

   /*

... */

   while(loop2)

{

     /*

... */

     if

(want_out)

   goto

end_loop1;

     /*

... */

   }

   /*

... */

 end_loop1:

;

}

前方参照  繰返し文(6.8.5

6.8.4

選択文

構文規則

選択文:

                              if    (

式    )    文

                              if    (

式    )    文    else    文

                              switch    (

式    )    文

意味規則  選択文は,制御式の値に応じて幾つかの文の中から一つを選択する。

選択文はブロックとする。そのブロックの有効範囲は,それを囲むブロックの有効範囲の真部分集合と

する。各副文もブロックとする。そのブロックの有効範囲は,選択文の有効範囲の真部分集合とする。

6.8.4.1

if

制約  if 文の制御式は,スカラ型をもたなければならない。

意味規則  両形式とも,式の値が 0 と比較して等しくない場合,最初の副文を実行する。else 形式の場

合,式の値が 0 と比較して等しいならば,2 番目の副文を実行する。ラベルを通して最初の副文に制御が

到達した場合,2 番目の副文は実行しない。

else

は,構文規則で許される if のうち,その else の前で最も近い位置にある if と結び付く。

6.8.4.2

switch


102

X 3010

:2003 (ISO/IEC 9899:1999)

     

制約  switch 文の制御式は,整数型をもたなければならない。

可変修飾型をもつ識別子の有効範囲の中にその switch 文に対応する case ラベル又は default ラベ

ルがある場合,switch 文全体がその識別子の有効範囲の中になければならない(

132

)

各 case ラベルの式は,整数定数式でなければならず,同一の switch 文の中で二つの case ラベルの

定数式が型変換後に同じ値をもっていてはならない。switch 文の中には,高々一つの default ラベル

があってもよい(ただし,内側の switch 文には,default ラベル又は外側の switch 文の case 定数

式と重複する値の case 定数式があってもよい。

意味規則  switch 文は,制御式の値,スイッチ本体(switch body)と呼ばれる文の中の default ラベル

の有無及び case ラベルの値に依存して,スイッチ本体,スイッチ本体の中の文又はスイッチ本体の次の

文に制御を移す。case ラベル又は default ラベルは,それを囲んでいる最も内側の switch 文の中だけ

で有効とする。

制御式に対して整数拡張を行う。各 case ラベルの定数式を制御式の拡張後の型に型変換する。型変換

した値が拡張した制御式の値と一致する場合,制御はその一致した case ラベルの直後の文に移る。型変

換した case 定数式のいずれとも一致しない場合,default ラベルがあれば制御はそのラベル付き文に移

る。default ラベルがなければ,スイッチ本体のいずれの部分も実行しない。

処理系限界  処理系は,switch 文における case ラベルの個数を制限してもよい(5.2.4.1 参照)。

例  次の作為的なプログラム片

switch (expr)

  {

int i = 4;

   f(i);

  case

0:

i = 17;

   /*

default

部へ抜ける */

  default:

   printf("%d

\n", i);

}

において,識別子が i のオブジェクトは,

(そのブロック内で)自動記憶域期間をもって存在す

るが,初期化されることはない。したがって,制御式が 0 以外の値をもつ場合,関数 printf の

呼出しは不定の値にアクセスすることになる。同様に関数 f の呼出しには,制御が到達しない。

6.8.5

繰返し文

構文規則

繰返し文:

                              while (

式  )    文

                              do

文    while (  式  ) ;

───────────────────────────────────────────────

(132)

つまり,その識別子の宣言は,switch 文より前にあるか,又はその宣言を含むブロックにある

switch

に関連する最後の case ラベル若しくは default ラベルより後にあるかのいずれかであ

る。


103

X 3010

:2003 (ISO/IEC 9899:1999)

     

                              for (

opt

 ;

opt

 ;

opt

 )

                              for (

宣言  式

opt

 ;

opt

 )

制約  繰返し文の制御式は,スカラ型をもたなければならない。

for

文の宣言部分で宣言できるのは,自動記憶域期間をもつオブジェクトだけとする(register 記憶

域クラス指定子があってもよい。

意味規則  繰返し文は,ループ本体(loop body)と呼ばれる文を,制御式が 0 と比較して等しくなるまで

の間,繰り返して実行する。

繰返し文はブロックとする。そのブロックの有効範囲は,それを囲むブロックの有効範囲の真部分集合

とする。ループ本体もブロックとする。そのブロックの有効範囲は,繰返し文の有効範囲の真部分集合と

する。

6.8.5.1

while

文  制御式の評価は,ループ本体の各実行の前に行う。

6.8.5.2

do

文  制御式の評価は,ループ本体の各実行の後に行う。

6.8.5.3

for

文  文

              for (

節 1 ;  式 2 ;  式 3 )    文

の動作は次のとおりとする。式 2 は制御式とし,ループ本体の各実行の前に評価する。式 3 はループ本体

の各実行の後にボイド式として評価する。節 1 が宣言である場合,そこで宣言する変数の有効範囲は宣言

の残り及び他の二つの式を含むループ全体とする。その宣言に到達するのは,制御式の最初の評価の前と

する。節 1 が式である場合,それは制御式の最初の評価の前にボイド式として評価する(

133

)

節 1 も式 3 も省略してよい。式 2 を省略した場合,0 でない定数によって置き換える。

6.8.6

分岐文

構文規則

分岐文:

                              goto

識別子  ;

                              continue ;

                              break ;

                              return

opt

 ;

意味規則  分岐文は,別の場所への無条件分岐を引き起こす。

6.8.6.1

goto

制約  goto 文の識別子は,その goto 文を含む関数内のどこかに位置するラベルを指定しなければなら

ない。goto 文は,可変修飾型をもつ識別子の有効範囲の外側からその識別子の有効範囲の内側へ分岐し

てはならない。

意味規則  goto 文は,その goto 文を含む関数内の指定されたラベルが付けられた文への無条件分岐を

引き起こす。

1.  複雑な文の集まりの途中に分岐することが便利な場合がある。次の三つの仮定が成立する場合

───────────────────────────────────────────────

(133)

すなわち,節 1 はループの初期化を指定し,ループの中で使用する一つ以上の変数を宣言してもよ

い。制御式である式 2 は,各繰返しの前に評価し,その式が 0 と比較して等しくなるまでループの

実行を継続することを指定する。式 3 は各繰返しの後に実行される演算(増加など)を指定する。


104

X 3010

:2003 (ISO/IEC 9899:1999)

     

の書き方の例を示す。

1.

共通の初期化コードは,実行中の関数で可視なオブジェクトだけにアクセスする。

2.

共通の初期化コードは,重複して記述するには大きすぎる。

3.

次に行うべき演算を決定するコードは,

(例えば,continue 文によって到達できるように

するために)ループの先頭にある。

/*

... */

 goto

first_time;

 for(;;)

{

   //

次の演算の決定

   /*

... */

   if

(

再初期化が必要) {

     //

再初期化だけのコード

     /*

... */

   first_time:

     //

共通の初期化コード

     /*

... */

     continue;

   }

   //

その他の演算の処理

   /*

... */

}

2.  goto 文は可変修飾型をもつオブジェクトの宣言を飛び越してはならない。しかし,有効範囲

の中の飛び越しは許される。

goto lab3;

//

正しくない:VLA の有効範囲に入る

{

   double

a[n];

a[j] = 4.4;

 lab3:

a[j] = 3.3

   goto

lab4;

  //

正しい:VLA の有効範囲内

a[j] = 5.5

 lab4:

a[j] = 6.6;

 }

 goto

lab4;

    //

正しくない:VLA の有効範囲に入る

6.8.6.2

continue

制約  continue 文は,ループ本体の中に又はループ本体としてだけ現れなければならない。

意味規則  continue 文は,それを囲む最も内側の繰返し文のループ継続部,すなわちループ本体の終わ

りへの分岐を引き起こす。より正確には,次の 3 種類の繰返し文

while (/*

... */ ) {


105

X 3010

:2003 (ISO/IEC 9899:1999)

     

/*

... */

continue;

/*

... */

 contin:

;

 }

 do

{

/*

... */

continue;

/*

... */

 contin:

;

} while (/*

... */);

 for

(/*

... */) {

/*

... */

continue;

/*

... */

 contin:

;

 }

の中で continue 文は goto  contin;(

134

)

と等価とする。ただし,continue 文が内側の繰返し文の中

にある場合(その場合,それはその繰返し文の中で解釈する。

)を除く。

6.8.6.3

break

制約  break 文は,スイッチ本体若しくはループ本体の中に,又はスイッチ本体若しくはループ本体とし

てだけ,現れなければならない。

意味規則  break 文は,それを囲む最も内側の switch 文又は繰返し文の実行を終了させる。

6.8.6.4

return

制約  式をもつ return 文は,void 型を返す関数の中に現れてはならない。式をもたない return 文は,

void

型を返す関数の中にだけ現れなければならない。

意味規則  return 文は,実行中の関数の実行を終了し,制御をその呼出し元に返す。一つの関数は,任

意の個数の return 文をもってもよい。

式をもつ return 文を実行すると,その式の値を関数呼出し式の値として呼出し元に返す。式が return

文を囲む関数の返却値の型と異なる型をもつ場合,その値は,その関数の返却値の型をもつオブジェクト

への代入と同じ規則で型変換する(

135

)

              struct s { double i; } f(void);

───────────────────────────────────────────────

(134)

ラベル contin:の後は空文である。

(135)

return

文は,代入でない。6.5.16.1 のオブジェクトの記憶域の重なりに関する制約は,関数から

の戻りの場合には適用しない。


106

X 3010

:2003 (ISO/IEC 9899:1999)

     

       union  {

               struct  {

                       int  f1;

                       struct  s  f2;

               }  u1;

               struct  {

                       struct  s  f3;

                       int  f4;

               }  u2;

       } g;

       struct  s  f(void)

       {

               return  g.u1.f2;

       }

       /*

... */

       g.u2.f3  =  f();

ここで,未定義の動作はないが,仮に(値を取得する関数呼出しを使わないで)代入が直接行わ

れるならば,未定義の動作が発生する。

6.9

外部定義

構文規則

翻訳単位:

外部宣言

翻訳単位    外部宣言

外部宣言:

関数定義

宣言

制約  記憶域クラス指定子 auto 及び register が,外部宣言の宣言指定子列の中に現れてはならない。

内部結合で宣言した識別子に対する外部定義が,一つの翻訳単位の中に二つ以上あってはならない。さ

らに,内部結合で宣言した識別子を式(結果が整数定数である sizeof 演算子のオペランドである場合を

除く。

)の中で使用する場合,同じ翻訳単位の中にその識別子に対する外部定義がちょうど一つなくてはな

らない。

意味規則  前処理後のプログラムテキストの単位を翻訳単位と呼ぶ(5.1.1.1 参照)。翻訳単位は一つ以上の

外部宣言から成る。外部宣言は,どの関数から見ても外側に現れる(したがって,ファイル有効範囲をも

つ。

)ので,

“外部”という。その識別子を名前とするオブジェクト又は関数のための記憶域の確保を伴う

宣言を定義という(6.7 参照)

(インライン定義以外の)関数の定義又はオブジェクトの定義ともなる外部宣言を

外部定義(external

definition

)という。外部結合で宣言した識別子を式(結果が整数定数である sizeof 演算子のオペランド


107

X 3010

:2003 (ISO/IEC 9899:1999)

     

である場合を除く。

)の中で使用している場合,プログラム全体のどこかにその識別子に対する外部定義が

ちょうど一つなければならない。使用していない場合,一つ以下でなければならない(

136

)

6.9.1

関数定義

構文規則

関数定義:

宣言指定子列    宣言子    宣言並び

opt

複合文

宣言並び:

宣言

宣言並び    宣言

制約  関数定義で宣言する識別子(その関数の名前)の型が関数型であることは,その関数定義の宣言子

の部分で指定しなければならない(

137

)

関数の返却値の型は,配列型以外のオブジェクト型又は void 型でなければならない。

宣言指定子列の中に記憶域クラス指定子がある場合,それは extern 又は static のいずれかでなけれ

ばならない。

宣言子が仮引数型並びを含む場合,

それぞれの仮引数の宣言は識別子を含まなければならない。

ただし,

仮引数型並びが void 型の仮引数一つだけから成る特別な場合を除く。この場合は,識別子があってはな

らず,更に宣言子の後ろに宣言並びが続いてはならない。

宣言子が識別子並びを含む場合,宣言並びの中の各宣言は,少なくとも一つの宣言子をもたなければな

らず,それらの宣言子は,識別子並びに含まれる識別子の宣言でなければならない。そして,識別子並び

の中のすべての識別子を宣言しなければならない。型定義名として宣言された識別子を仮引数として再宣

言してはならない。宣言並びの中の宣言は,register 以外の記憶域クラス指定子及び初期化を含んでは

ならない。

意味規則  関数定義の宣言子は,定義される関数の名前及びその仮引数の識別子を指定する。宣言子が仮

引数型並びを含む場合,その仮引数型並びがすべての仮引数の型も指定する。この場合は,同じ翻訳単位

のこれ以降の部分で同じ関数を呼び出すための関数原型としても働く。宣言子が識別子並びを含む場合

───────────────────────────────────────────────

(136)

すなわち,外部結合で宣言した識別子を式の中で使用しない場合,その外部定義は必要ではない。

(137)

これは,関数定義の型を typedef から受け継ぐことはできないことを意味する。

                typedef int F(void);

//

型 F は“仮引数をもたず,int を返す関数”

        F  f,  g;

//  f

と g はいずれも F と適合する型をもつ

        F  f  {  /*

... */ }   //

誤:構文エラー/制約違反

        F  g()  {  /*

... */ }

//

誤:g が関数を返すことになる

        int  f(void)  {  /*

... */ }

//

正:f は F と適合する型をもつ

        int  g()  {  /*

... */ }

//

正:g は F と適合する型をもつ

        F  *e(void)  {  /*

... */ }  //

e

は関数へのポインタを返す

        F  *((e))(void)  {  /*

... */ }

//

同上,括弧は無関係

        int  (*fp)(void);

//  fp

は型 F の関数を指す

        F  *Fp;

//  Fp

は型 F の関数を指す


108

X 3010

:2003 (ISO/IEC 9899:1999)

     

(

138

)

,仮引数の型はその後ろに続く宣言並びで宣言しなければならない。いずれの場合でも,各仮引数の

型は,仮引数型並びに対する 6.7.5.3 の規定に従って型調整する。型調整した結果の型はオブジェクト型で

なければならない。

可変個数の実引数を受け付ける関数を,省略記号表記で終わる仮引数型並びを使わずに定義した場合,

その動作は未定義とする。

各仮引数は,自動記憶域期間をもつ。その識別子は左辺値とし,関数本体を構成する複合文の先頭で宣

言されたとみなす(このため,関数本体では更に内側のブロックの中以外では再宣言できない。

。仮引数

のための記憶域の配置は,未規定とする。

関数の入り口で,可変修飾された各仮引数の大きさを指定する式を評価し,各実引数式の値を代入の場

合と同じ方法で,対応する仮引数の型に変換する(実引数としての配列式及び関数指示子は呼出しの前に

ポインタに変換済みである。

すべての仮引数への代入の後,関数定義の本体を構成する複合文を実行する。

関数を終了させる}に到達し,かつ関数呼出しの値を呼出し元が使う場合,その動作は未定義とする。

1.

              extern int max(int a, int b)

       {

               return  a  >  b  ?  a  :  b;

       }

この例の中で,extern は記憶域クラス指定子,int は型指定子である。max(int a, int b)

は関数宣言子であり,

       { return a > b ? a : b; }

は関数本体である。この関数定義と類似の次の例では,仮引数の宣言に識別子並びの形式を使

用している。

       extern  int  max(a,  b)

       int  a,  b;

       {

               return  a  >  b  ?  a  :  b  ;

       }

ここで,int a, b;は仮引数に対する宣言並びとなる。これら二つの定義の違いは,最初の形

式が関数の呼出し時に強制的に実引数の型変換を行う関数原型の宣言として働くのに対し,2

番目の形式ではそのような動作は行わないという点である。

2.  ある関数を別の関数に渡す場合,次のように書ける。

       int  f(void);

      /*

... */

       g(f);

このとき,g の定義は

        void  g(int  (*funcp)(void))

───────────────────────────────────────────────

(138)

“今後の言語の方針”

6.11.7)参照。


109

X 3010

:2003 (ISO/IEC 9899:1999)

     

       {

               /*

... */

               (*funcp)();     /*

又は funcp() ... */

       }

又は

        void  g(int  func(void))

       {

               /*

... */

               func();         /*

又は(*func)() ...   */

       }

とすればよい。

6.9.2

外部オブジェクト定義

意味規則  オブジェクトの識別子の宣言がファイル有効範囲及び初期化子をもつ場合,その宣言を識別子

の外部定義という。

ファイル有効範囲のオブジェクトの識別子を,初期化子を使わず,かつ,記憶域クラス指定子なしか又

は記憶域クラス指定子 static で宣言する場合,そのオブジェクトの識別子の宣言を

仮定義(tentative

definition

)という。翻訳単位が,ある識別子に対する仮定義を一つ以上含み,かつその識別子に対する外

部定義を含まない場合,その翻訳単位に,翻訳単位の終わりの時点での合成型,及び 0 に等しい初期化子

をもったその識別子のファイル有効範囲の宣言がある場合と同じ規則で動作する。

オブジェクトに対する識別子の宣言が仮定義であり,内部結合をもつ場合,その宣言の型は不完全型で

あってはならない。

1.

int i1 = 1;

//

定義,外部結合

static int i2 = 2;

//

定義,内部結合

extern int i3 = 3;

//

定義,外部結合

int

i4;   //

仮定義,外部結合

static int i5;

//

仮定義,内部結合

int

i1;   //

正しい仮定義,前の定義を参照する

int

i2;   //

前に内部結合をもつ定義があるため,

    //

結合の不一致が生じ,6.2.2 によって

    //

動作は未定義となる

int

i3;   //

正しい仮定義,前の定義を参照する

int

i4;   //

正しい仮定義,前の定義を参照する

int

i5;   //

前に内部結合をもつ定義があるため,

    //

結合の不一致が生じ,6.2.2 によって

    //

動作は未定義となる

extern int i1;

//

外部結合をもつ前の定義を参照する

extern int i2;

//

内部結合をもつ前の定義を参照する


110

X 3010

:2003 (ISO/IEC 9899:1999)

     

extern int i3;

//

外部結合をもつ前の定義を参照する

extern int i4;

//

外部結合をもつ前の定義を参照する

extern int i5;

//

内部結合をもつ前の定義を参照する

2.  翻訳単位が

int i[];

を含み,その翻訳単位の最後で,配列 i が依然として不完全型をもつ場合,配列 i は暗黙の初

期化子によって一つの要素をもつようにされる。その要素にはプログラム開始時に 0 がセット

される。

6.10

前処理指令

構文規則

前処理ファイル:

グループ

opt

グループ:

グループ構成要素

グループ    グループ構成要素

グループ構成要素:

                              if

制御行

テキスト行

                              #

未定義指令

              if

節:

                              if

グループ  elif グループ列

opt

    else

グループ

opt

    endif

              if

グループ:

                              # if

定数式    改行    グループ

opt

                              # ifdef

識別子    改行    グループ

opt

                              # ifndef

識別子    改行    グループ

opt

              elif

グループ列:

                              elif

グループ

                              elif

グループ列  elif グループ

              elif

グループ:

                              # elif

定数式    改行    グループ

opt

              else

グループ:

                              # else

改行    グループ

opt

              endif

行:

                              # endif

改行

制御行:

                              # include

前処理字句列    改行

                              # define

識別子    置換要素並び    改行


111

X 3010

:2003 (ISO/IEC 9899:1999)

     

                              # define

識別子    左括弧    識別子並び

opt

    )

置換要素並び    改行

                              # define

識別子    左括弧    ...)    置換要素並び    改行

                              # define

識別子    左括弧    識別子並び  , ...)    置換要素並び    改行

                              # undef

識別子    改行

                              # line

前処理字句列    改行

                              # error

前処理字句列

opt

改行

                              # pragma

前処理字句列

opt

改行

                              #

改行

テキスト行:

前処理字句列

opt

改行

未定義指令:

前処理字句列    改行

左括弧:

空白類が直前にない(文字

置換要素並び:

前処理字句列

opt

前処理字句列:

前処理字句

前処理字句列    前処理字句

改行:

改行文字

補足説明  前処理指令は,[翻訳フェーズ(4)の最初で]次の二つの条件のいずれかを満たす#前処理字

句で始まり,それに続く最初の改行文字で終わる一連の前処理字句とする(

139

)

−  ソースファイル中の最初の文字である(改行文字を含まない空白類の後であってもよい。

−  少なくとも一つの改行文字を含む空白類の後に続く。改行文字は前処理指令を終わらせる(前処理指

令がなかったとしたら関数形式マクロの呼出しとなる場合においても,改行文字はその前処理指令を

終わらせる。

参考  関数形式マクロの呼出しの中の改行文字の扱いについては,6.10.3 参照。

テキスト行は,#前処理字句で始まってはならない。未定義指令は構文規則にある指令の名前で始まっ

てはならない。

読み飛ばされるグループ(6.10.1)の中では,指令の構文規則を緩和して,指令の名前とそれに続く改行

文字の間に任意の前処理字句の並びを置くことを可能とする。

制約  前処理指令の中(先頭の#前処理字句の直後から,最後の改行文字の直前まで)の前処理字句の間

に現れてよい空白類文字は,空白と水平タブだけとする[翻訳フェーズ(3)において注釈,又はその他の

───────────────────────────────────────────────

(139)

このため,一般に前処理指令を“行”と呼ぶ。これらの“行”には,これ以外の構文的意味はない。

前処理中の特定の場合(例えば,6.10.3.2 の#文字列リテラル作成演算子を参照)を除いて,すべて

の空白類は等価だからである。


112

X 3010

:2003 (ISO/IEC 9899:1999)

     

空白類文字を置き換えた空白を含む。

意味規則  処理系は,ソースファイルの一部分を条件によって処理したり読み飛ばしたり,他のソースフ

ァイルを組み込んだり,マクロを置き換えたりすることができる。これらの処理は,概念的にはその翻訳

単位の翻訳の前に行うので,

前処理(preprocessing)と呼ぶ。

前処理指令の中の前処理字句は,この規格で異なる規定を行わない限り,マクロ展開の対象とはならな

い。

             #define  EMPTY

       EMPTY  #include  <file.h>

2

行目の前処理字句の並びは,前処理指令ではない。これは,翻訳フェーズ(4)の最初で#で始

まらないからである(EMPTY が置き換えられた後なら#で始まるのだが。

6.10.1

条件付き取込み

制約  条件付き取込みを制御する式は,整数定数式でなければならない。ただし,キャストを含んではな

らず,識別子(キーワードと字句的に等しい識別子を含む。

)は次の

意味規則に従って解釈する(

140

)

。さら

に,次の形式の単項演算子式を含んでもよい。

              defined

識別子

又は

              defined    (

識別子  )

これらの単項演算子式の評価の結果は,

識別子をその時点でマクロ名として定義している場合

(すなわち,

あらかじめ定義されているか,又は#define 前処理指令の対象になっていて,しかもその後にその同じ識

別子を対象とした#undef 前処理指令がない場合)1 と評価し,そうでない場合 0 と評価する。

意味規則  次の形式の前処理指令

              # if

定数式        改行        グループ

opt

              # elif

定数式        改行        グループ

opt

は,制御定数式を評価した結果が 0 以外かどうかを検査する。

評価に先立って,制御定数式となる前処理字句列の中のマクロ呼出しを,普通のテキストと同様に

(defined 単項演算子のオペランドとなるマクロ名を除いて)置き換える。この置き換えによって字句

defined

が生成される場合,又は defined 単項演算子のマクロ置き換え前の使用法が,

制約の中で規定

した二つの形式のいずれにも一致しない場合,その動作は未定義とする。マクロ展開及び defined 単項

演算子によるすべてのマクロ置き換えの実行後,残っているすべての識別子を前処理数 0 で置き換えてか

ら,各前処理字句を字句に変換する。変換後の字句は制御定数式を構成する。この式は,6.6 の規定に従っ

て評価する。

ただし,

すべての符号付き整数型及びすべての符号無し整数型がそれぞれヘッダ<stdint.h>

で定義する型 intmax_t 及び uintmax_t と同じ表現をもつとの仮定の下で動作することを除く。これは

文字定数の解釈を含み,その解釈は逆斜線表記から実行文字集合の要素への変換を伴ってもよい。文字定

数に対応する数値が,

(#if 又は#elif 指令の中以外の)式の中に同一の文字定数が現れたとき得られる

───────────────────────────────────────────────

(140)

制御定数式は,翻訳フェーズ(4)において評価するので,識別子にはマクロ名であるか否かの区

別しかない。すなわち,キーワード,列挙定数などはまだ存在しない。


113

X 3010

:2003 (ISO/IEC 9899:1999)

     

値と一致しているか否かは,処理系定義とする(

141

)

。さらに,単一文字から成る文字定数が負の値をもっ

てもよいか否かは,処理系定義とする。

次の形式の前処理指令

              # ifdef

識別子        改行        グループ

opt

              # ifndef

識別子        改行        グループ

opt

は,識別子をその時点でマクロ名として定義しているか否かを検査する。これらの前処理指令は,それぞ

れ“#if defined  識別子”及び“#if !defined  識別子”と等価とする。

各指令の条件は,順番に検査する。その条件の評価結果が偽(0)であった場合,それが制御するグルー

プを読み飛ばす。このとき,そのグループ内の前処理指令は,指令の種類を決める名前までを処理して,

if

節の入れ子のレベルを追跡するためにだけ用いる。前処理指令のそれ以降の前処理字句及びグループ内

の他の前処理字句は,すべて無視する。条件が真(0 以外)と評価された最初のグループだけを処理する。

どの条件も偽の場合,#else 指令があるときは,#else で制御されるグループを処理し,#else 指令が

ないときは,#endif までのすべてのグループを読み飛ばす(

142

)

前方参照  最大幅整数型(7.18.1.5),ソースファイル取込み(6.10.2),マクロ置き換え(6.10.3

6.10.2

ソースファイル取込み

制約  #include 指令は,処理系で処理可能なヘッダ又はソースファイルを識別しなければならない。

意味規則  次の形式の前処理指令

              # include        <h

文字列>        改行

は,処理系定義の場所を順に探索して,<区切り記号と>区切り記号の間で指定した文字列で一意に決まる

ヘッダを見つけ,そのヘッダの内容全体でこの指令を置き換える。どのようにして探索の場所を指定する

か,またどのようにしてヘッダを識別するかは,処理系定義とする。

次の形式の前処理指令

              # include        "q

文字列"        改行

は,二つの"区切り記号の間で指定した文字列で一意に決まるソースファイルの内容全体で,この指令を

置き換える。指定したソースファイルの探索手順は処理系定義とする。この探索をサポートしていない場

合,又は探索が失敗した場合,同じ文字列(もしあれば>文字を含めて)を含む次の指令に読み替えたの

と同じ規則で再処理する。

              # include        <h

文字列>        改行

次の(上の二つの形式のいずれとも一致しない)形式の前処理指令

              # include

前処理字句列        改行

も許す。この指令の中の,include の後ろにある前処理字句列は,通常のテキストと同様に処理する(そ

の時点でマクロ名として定義している各識別子は,その識別子の置換要素並びの前処理字句列に置き換え

───────────────────────────────────────────────

(141)

すなわち,次の#if 指令と if 文の中の定数式が,この二つの文脈の中で同じ値として評価される

という保証はない。

                #if 'z'-'a' == 25

        if  ('z'-'a'  ==  25)

(142)

構文で示したように,

#else

指令又は#endif 指令の改行文字の前に前処理字句を続けてはならな

い。しかし,注釈は前処理指令の中を含めてソースファイルのどこに現れてもよい。


114

X 3010

:2003 (ISO/IEC 9899:1999)

     

る。

。すべての置き換えを行った後の指令は,この箇条で規定する二つの形式のうちのいずれかと一致し

なければならない(

143

)

。前処理字句<と>,又は二つの"文字の対に囲まれた前処理字句列を,一つのヘッダ

名の前処理字句に解釈する方法は,処理系定義とする。

処理系は,一つ以上の英字又は数字(5.2.1 で定義する)の列の後ろにピリオド(.)及び一つの英字が

続く形式に対して,一意の対応付けを提供しなければならない。最初の文字は,英字でなければならない。

処理系は,アルファベットの大文字と小文字の区別を無視してもよく,対応付けはピリオドの前 8 文字に

対してだけ有効であると限定してもよい。

#include

前処理指令は,入れ子になっていてもよい。すなわち,処理系定義の入れ子の制限(5.2.4.1

参照)の範囲内で,他のファイルの#include 前処理指令によって取り込まれたソースファイルの中に現

れてもよい。

1.  #include 前処理指令として,最も一般的な用法を次に示す。

        #include  <stdio.h>

       #include  "myprog.h"

2.  次の例は,マクロ置き換えする#include 指令を示している。

            #if VERSION == 1

               #define  INCFILE  "vers1.h"

       #elif  VERSION  ==  2

               #define  INCFILE  "vers2.h"       //

以下同様

        #else

               #define  INCFILE  "versN.h"

       #endif

       #include  INCFILE

前方参照  マクロ置き換え(6.10.3

6.10.3

マクロ置き換え

制約  二つの置換要素並びは,その前処理字句列の個数,順序,つづり及び空白類による区切り方が同じ

場合,そしてその場合に限り,同一の並びとみなす。ただし,空白類による区切りは,いずれも同じもの

とみなす。

オブジェクト形式マクロとしてその時点で定義されている識別子は,次の条件を満たす場合に限り,他

の#define 前処理指令によって再定義してもよい。

−  2 番目の定義がオブジェクト形式マクロ定義である。

−  二つの置換要素並びが同一である。

関数形式マクロとしてその時点で定義されている識別子は,次の条件を満たす場合に限り,他の#define

前処理指令によって再定義してもよい。

−  仮引数の個数とつづりが最初の定義と同一な関数形式マクロの定義である。

−  二つの置換要素並びが同一である。

オブジェクト形式マクロの定義では,識別子と置換要素並びの間に空白類がなければならない。

───────────────────────────────────────────────

(143)

隣接した文字列リテラルが,連結して一つの文字列リテラルになることはない(5.1.1.2 の翻訳フェ

ーズ参照)

。したがって,展開の結果二つの文字列リテラルが現れると正しくない指令行となる。


115

X 3010

:2003 (ISO/IEC 9899:1999)

     

マクロ定義の中の識別子並びが省略記号で終わっていない場合は,関数形式マクロの呼出しにおける実

引数(前処理字句 0 個から成る実引数を含める)の個数は,マクロ定義内の仮引数の個数と一致しなけれ

ばならない。逆に,識別子並びが省略記号で終わる場合は,マクロ呼出しにおける実引数の個数は,マク

ロ定義内の仮引数(...  を除く)の個数より多くなければならない。いずれの場合も,呼出しの終了を示

す)前処理字句がなければならない。

識別子_ _VA_ARGS_ _は,仮引数に省略記号表記を用いる関数形式マクロにおける置換要素並びの中だ

けに現れなければならない。

関数形式マクロにおける仮引数識別子は,その有効範囲内で同じものを二つ以上宣言してはならない。

意味規則  define の直後に記述してある識別子を,マクロ名(macro name)という。マクロ名に対する

名前空間が一つだけ存在する。いずれのマクロ形式においても,置換要素並びの前処理字句列の前又は後

に続く一つ以上の空白類文字を,置換要素並びの一部とはみなさない。

字句的に前処理指令の始まりとして許される位置に,#前処理字句に続いて識別子が現れた場合,その

識別子はマクロ置き換えの対象とはならない。

次の形式の前処理指令

              # define

識別子  置換要素並び  改行

は,

オブジェクト形式マクロ(object-like macro)を定義する。それ以降,そのマクロ名(

144

)

の出現を,こ

の指令の残りを構成する置換要素並びの前処理字句列で置き換える。

次の形式の前処理指令

            # define

識別子  左括弧  識別子並び

opt

 )

置換要素並び  改行

            # define

識別子  左括弧  ... )  置換要素並び  改行

            # define

識別子  左括弧  識別子並び  , ... )  置換要素並び  改行

は,関数呼出しと同様の構文の,実引数をもつ

関数形式マクロ(function-like macro)を定義する。仮引数

は,省略可能な識別子並びで指定する。仮引数の有効範囲は,識別子並びの中の宣言から,#define 前処

理指令の終わりの改行文字までとする。これ以降,この関数形式マクロ名の次の前処理字句として(が現

れたときは,マクロ名からこの(前処理字句に対応する)前処理字句までの前処理字句列を,この定義内の

置換要素並びで置き換える(マクロ呼出し)

。この際,間に左右対となる括弧前処理字句があっても,これ

らを無視する。関数形式マクロの呼出しを構成する前処理字句列の中では,改行は普通の空白類文字とみ

なす。

最も外側の括弧によって囲まれた前処理字句の列は,関数形式マクロの実引数の並びを形成する。並び

の中の個々の実引数は,コンマ前処理字句によって区切る。ただし,内側に対をなす括弧がある場合,そ

の中のコンマ前処理字句は,実引数を区切るものではない。実引数の並びの中に,ほかの場合であれば前

処理指令として働く前処理字句列がある場合,その動作は未定義とする。

マクロ定義の中の識別子並びに...が存在する場合,それらを区切るコンマ前処理字句も含め,それ以

後の実引数をまとめて単一の構成要素に結合する。これを

可変個数の実引数(variable argument)という。

このように結合した場合の実引数の個数は,マクロ定義の中の(...を除く)仮引数の個数より一つ多い

───────────────────────────────────────────────

(144)

マクロ置き換えのときには,すべての文字定数と文字列リテラルは前処理字句であり,識別子のよ

うな部分列を含みうる文字の並びではないので(5.1.1.2 翻訳フェーズ参照)

,マクロ名や仮引数を

探すためにこれらの中を走査することはない。


116

X 3010

:2003 (ISO/IEC 9899:1999)

     

個数とする。

6.10.3.1

実引数置換  関数形式マクロの実引数を識別した後,実引数置換を行う。実引数の中に含まれる

すべてのマクロの展開後,置換要素並びの中の仮引数を対応する実引数で置き換える。ただし,次の仮引

数は除く(6.10.3.2 及び 6.10.3.3 参照)

−  #前処理字句又は##前処理字句が前にある仮引数

−  ##前処理字句が後に続く仮引数

実引数置換の前に,実引数の前処理字句列を完全にマクロ置き換えする。このとき,実引数ごとに,その

前処理字句列が,現在の前処理ファイルの残りとなっているものとみなして処理する。つまり,他の前処

理字句列が存在しないかのように扱われる。

置換要素並びの中に現れる識別子_ _VA_ARGS_ _は,それが一つの仮引数であるかのように扱わなけれ

ばならない。それを,可変個数の実引数が形成する前処理字句列で置き換える。

6.10.3.2

  #

演算子

制約  関数形式マクロの置換要素並びの中にある各#前処理字句の次の前処理字句は,仮引数でなければ

ならない。

意味規則  置換要素並びの中で,仮引数の直前に#前処理字句がある場合,対応する実引数の前処理字句

列のつづりを含んだ一つの単純文字列リテラル前処理字句によって,#前処理字句と仮引数を置き換える。

実引数の前処理字句の間にある各空白類は,その単純文字列リテラルの中で一つの空白文字になる。実引

数の最初の前処理字句の前の空白類と,最後の前処理字句の後ろの空白類は,削除する。これらを除けば,

実引数の各前処理字句の元のつづりが,そのまま単純文字列リテラルの中で保持される。ただし,文字列

リテラルと文字定数のつづりを正しく生成するため,次の特別な処理を行う。

−  文字定数又は文字列リテラルの(区切りのための"文字も含めた)"文字及び\文字の前に,\文字を挿

入する処理

−  国際文字名の最初の\文字の前に\文字を挿入する処理。ただし,この処理を行うか否かは処理系定義

とする。

置き換えの結果が正しい単純文字列リテラルでない場合,その動作は未定義とする。空の実引数に対応す

る単純文字列リテラルは""とする。#演算子及び##演算子の評価順序は,未規定とする。

6.10.3.3

  ##

演算子

制約  ##前処理字句は,マクロ定義のいずれの形式においても,置換要素並びの先頭又は終わりに現れて

はならない。

意味規則  関数形式マクロの置換要素並びの中で,仮引数の直前又は直後に##前処理字句がある場合,そ

の仮引数を対応する実引数の前処理字句列で置き換える。ただし,実引数が前処理字句 0 個である場合,

仮引数を

プレースマーカ(placemarker)前処理字句で置き換える(

145

)

オブジェクト形式マクロ及び関数形式マクロのいずれの呼出しにおいても,更に置き換えるべきマクロ

名があるかどうかを調べるためにその置換要素並びを再検査する前に,置換要素並びの##前処理字句(実

引数の中の##前処理字句を除く)を削除し,その直前にある前処理字句をその直後の前処理字句と連結す

る。プレースマーカ前処理字句は特別に扱う。すなわち,二つのプレースマーカ前処理字句を連結すると,

───────────────────────────────────────────────

(145)

プレースマーカ前処理字句は,翻訳フェーズ(4)内部でだけ一時的に存在するため,構文規則の

中には現れない。


117

X 3010

:2003 (ISO/IEC 9899:1999)

     

一つのプレースマーカ前処理字句となる。プレースマーカ前処理字句と,プレースマーカでない前処理字

句を連結すると,そのプレースマーカでない前処理字句となる。その結果が正しい前処理字句にならない

場合,その動作は未定義とする。その結果の字句はその後のマクロ置き換えの対象となる。##演算子の評

価順序は,未規定とする。

例  次に示すプログラム片では,

            #define hash_hash # ## #

      #define  mkstr(a)  #  a

      #define  in_between(a)  mkstr(a)

      #define  join(c,  d)  in_between(c  hash_hash  d)

      char  p[]  =  join(x,  y);  // char p[] = "x ## y";

と等価

展開によって,段階的に次に示す結果が生成される。

       join(x,  y)

      in_between(x  hash_hash  y)

      in_between(x  ##  y)

      mkstr(x  ##  y)

      "x  ##  y"

すなわち,hash_hash を展開して,二つのシャープ記号から成る新しい字句を生成する。しか

し,この新しい字句は##演算子ではない。

6.10.3.4

再走査と再置き換え  置換要素並び中のすべての仮引数を置き換え,更に#演算子及び##演算子

の処理を行った後,すべてのプレースマーカ前処理字句を削除する。その後,更に置き換えるべきマクロ

名があるかどうかを調べるために,ソースファイル上のその後のすべての前処理字句とともにその結果の

前処理字句を再走査する。

現在置き換え中のマクロの名前を,

(ソースファイルの残りの前処理字句列は含まない)

置換要素並びの

この走査中に検出した場合,置き換えは行わない。さらに,入れ子になった置き換えで現在置き換え中の

マクロの名前を検出した場合も,置き換えは行わない。これらの置き換えられなかったマクロ名の前処理

字句列は,たとえ,他の場合であれば置き換えが起きる文脈上で(再)検査しても,もはや置き換えの対

象とはならない。

完全にマクロ置き換えした結果の前処理字句列は,前処理指令の形をしていたとしても,前処理指令と

して処理することはない。ただし,その結果の中のすべてのプラグマ単項演算子式については,6.10.9 

規定に従って処理する。

6.10.3.5

マクロ定義の有効範囲  マクロ定義は,(ブロック構造とは独立に)対応する#undef 指令を検出

するまで,又は(#undef 指令がなければ)前処理翻訳単位の最後まで有効とする。マクロ定義は翻訳フ

ェーズ(4)の後は意味をもたない。

次の形式の前処理指令

            #undef

識別子  改行


118

X 3010

:2003 (ISO/IEC 9899:1999)

     

は,指定された識別子のマクロ名としての定義を無効にする。指定された識別子がその時点でマクロ名と

して定義されていない場合,この指令を無視する。

1.  マクロ機能の最も単純な使用法は,例えば次のような“定数名”の定義である。

            #define TABSIZE 100

      int  table[TABSIZE];

2.  次の例では,実引数の中で最大のものを値とする関数形式マクロを定義している。このマクロ

は,

−  適合する型であればどんな型の実引数に対しても動作する。

−  関数呼出しのオーバヘッドのないインラインコードを生成する。

という利点をもち,

−  実引数の一方を(副作用を含め)2 回評価する。

−  何度も呼び出される場合に,関数に比べコードを多く生成する。

という欠点をもつ。さらに,アドレスをもたないので,アドレスを得ることもできない。

      #define max(a, b) ((a) > (b) ? (a) : (b))

括弧は,実引数と結果の式が正しく演算子と結合されることを保証する。

3.  再定義と再検査の例を次に示す。

      #define  x

3

      #define  f(a)

f(x  *  (a))

      #undef

x

      #define  x

2

      #define  g

f

      #define  z

z[0]

      #define  h

g(~

      #define  m(a)

a(w)

      #define  w

0,1

      #define  t(a)

a

      #define  p()

int

      #define  q(x)

x

      #define  r(x,y)

x  ##  y

      #define  str(x)

#  x

      f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);

      g(x+(3,4)-w)  |  h  5)  &  m

            (f)^m(m);

      p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };

      char  c[2][6]  =  {  str(hello),  str()  };

上の例は,次の結果になる。

       f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);

      f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);


119

X 3010

:2003 (ISO/IEC 9899:1999)

     

      int  i[]  =  {  1,  23,  4,  5,  };

      char  c[2][6]  =  {  "hello",  ""  };

4.  単純文字列リテラルの生成及び字句の列の連結の規則の例を次に示す。

      #define  str(s) #  s

      #define  xstr(s)

str(s)

      #define debug(s, t)

printf("x" # s "= %d, x" # t "= %s",

                                     x ## s, x ## t)

      #define  INCFILE(n)

vers  ##  n

      #define  glue(a,  b)

a  ##  b

      #define  xglue(a,  b)

glue(a,  b)

      #define  HIGHLOW

"hello"

      #define  LOW

LOW  ",  world"

      debug(1,  2);

            fputs(str(strncmp("abc

\0d", "abc", '\4') //

この注釈はなくなる

                   ==  0)  str(:  @

\n), s);

      #include  xstr(INCFILE(2).h)

      glue(HIGH,  LOW);

      xglue(HIGH,  LOW)

上の例は,次の結果になる。

      printf("x" "1" "= %d, x" "2" "= %s", x1, x2);

      fputs("strncmp(

\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n",s);

      #include  "vers2.h"

        (

マクロ置き換え後,ファイルアクセス前)

       "hello";

      "hello"  ",  world"

さらに,単純文字列リテラルの連結を行い,最終的には次の結果になる。

      printf("x1=  %d,  x2=  %s",  x1,  x2);

      fputs("strncmp(

\"abc\\0d\", \"abc\", '\\4') == 0: @\n",s);

      #include  "vers2.h"

        (

マクロ置き換え後,ファイルアクセス前)

       "hello";

      "hello,  world"

マクロ定義における#字句及び##字句の前後の空白は,あってもなくてもよい。

5.  プレースマーカ前処理字句の規則の例を次に示す。

      #define t(x,y,z) x ## y ## z

      int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),

                 t(10,,),  t(,11,),  t(,,12),  t(,,)  };

上の例は,次の結果になる。

      int j[] = { 123, 45, 67, 89,

                  10,  11,  12,  };

6.  再定義の規則の例を次に示す。次の再定義は正しい。


120

X 3010

:2003 (ISO/IEC 9899:1999)

     

       #define  OBJ_LIKE      (1-1)

       #define  OBJ_LIKE        /*

空白類 */ (1-1) /* その他 */

       #define  FUNC_LIKE(a)   (  a  )

       #define  FUNC_LIKE(  a  )(  /*

空白類に注意 */  \

                               a /*

一部が別の行

                                   */ )

しかし次の再定義は正しくない。

      #define  OBJ_LIKE    (0)

//

字句の並びが違う

      #define  OBJ_LIKE    (1  -  1)

//

空白類が違う

      #define  FUNC_LIKE(b)  (  a  )

//

仮引数の使用法が違う

      #define  FUNC_LIKE(b)  (  b  )

//

仮引数のつづりが違う

7.  最後に,可変個数の実引数の例を示す。

      #define  debug(...)

fprintf(stderr,  _

 _VA_ARGS_ _)

      #define  showlist(...) puts(#_

 _VA_ARGS_ _)

      #define  report(test,  ...)  ((test)?puts(#test):

                  printf(_

 _VA_ARGS_ _))

       debug("Flag");

      debug("X  =  %d

\n", x);

      showlist(The  first,  second,  and  third  items.);

      report(x>y, "x is %d but y is %d", x, y);

上の例は,次の結果になる。

      fprintf(stderr,  "Flag"  );

      fprintf(stderr,  "X  =  %d

\n", x );

      puts( "The first, second, and third items." );

      ((x>y)?puts("x>y"):

                  printf("x  is  %d  but  y  is  %d",  x,  y));

6.10.4

行制御

制約  #line 指令の文字列リテラルは(それが存在する場合),単純文字列リテラルでなければならない。

意味規則  現在のソース行の行番号(line number)は,ソースファイルの翻訳フェーズ(1)(5.1.1.2 参照)

の処理において,現在の字句までに読み込んだ改行文字の個数より 1 だけ大きい。

次の形式の前処理指令

            # line

数字列  改行

は,処理系に対し,この指令以後のソース行の列が数字列(10 進整数として解釈する。

)で指定された行

番号で始まるものとして動作する。数字列は,0 を指定してはならず,また 2147483647 より大きい数も指

定してはならない。

次の形式の前処理指令

            # line

数字列  "s文字列

opt

"

改行

は,同様にみなし行番号を設定し,単純文字列リテラルの内容で,みなしソースファイル名を置き換える。

次の(上の二つの形式のいずれとも一致しない)形式の前処理指令

            # line

前処理字句列  改行


121

X 3010

:2003 (ISO/IEC 9899:1999)

     

も許す。この指令の line の後にある前処理字句列は,通常のテキストにある場合と同じように処理する

(その時点でマクロ名として定義されている各識別子は,その前処理字句列の置換要素並びによって置き

換える。

)すべての置き換えの結果の指令は,先の二つの形式のいずれかと一致しなければならない。一致

した形式の規則に従って処理する。

6.10.5

エラー指令

意味規則  次の形式の前処理指令

            # error

前処理字句列

opt

改行

は,処理系に対し,指定された前処理字句の列を含む診断メッセージを出力することを指示する。

6.10.6

プラグマ指令

意味規則  次の形式の前処理指令

            # pragma

前処理字句列

opt

改行

[ただし,

(マクロ置き換えに先だって(

146

)

)pragma の直後の前処理字句が STDC ではない]は,処理系

に対し処理系定義の方法で動作することを指示する。この動作の結果,翻訳に失敗してもよいし,翻訳プ

ログラム若しくは結果のプログラムが規格に合致しない動作をしてもよい。処理系が認識できないプラグ

マ指令は,無視する。

(マクロ置き換えに先だって)pragma の直後の前処理字句が STDC である場合,この指令に対してマ

クロ置き換えは行わない。この場合,この指令は次の形式(

147

)

のいずれか一つでなければならない。これ

らの意味はこの規格の別の場所で規定する。

            #pragma STDC FP_CONTRACT

状態切替え指定

            #pragma STDC FENV_ACCESS

状態切替え指定

            #pragma STDC CX_LIMITED_RANGE

状態切替え指定

状態切替え指定:  次のいずれか

                                  ON OFF DEFAULT

前方参照  CX_LIMITED_RANGE プラグマ(7.3.4),FENV_ACCESS プラグマ(7.6.1),FP_CONTRACT プ

ラグマ(7.12.2

6.10.7

空指令

意味規則  次の形式の前処理指令

          #

改行

は,何の効果もない。

6.10.8

あらかじめ定義されたマクロ名  次に掲げる七つのマクロ名(

148

)

は,処理系によって定義されてい

───────────────────────────────────────────────

(146)

処理系は,プラグマの中でマクロ置き換えを行う必要はない。しかし,標準のプラグマ(pragma

の直後に STDC が続くもの)を除き,マクロ置き換えを行うことは許されている。標準でないプラ

グマにおいてマクロ置き換えを行った結果が,標準のプラグマと同じ形式になる場合の動作も,処

理系定義である。それが標準のプラグマであるかのように動作してもよい。しかし,そのように動

作する必要はない。

(147)

“今後の言語の方針”

6.11.8)参照。

(148)

“今後の言語の方針”

6.11.9)参照。


122

X 3010

:2003 (ISO/IEC 9899:1999)

     

なければならない。

_

 _DATE_ _

前処理翻訳単位の翻訳の日付("Mmm dd yyyy"の形式をもつ単純文

字列リテラルで,月の名前は asctime 関数で生成されるものと同じ

とする。dd の値が 10 より小さいときは,その最初の文字は空白とす

る。

。翻訳の日付が得られない場合,処理系定義の正しい日付を提供

しなければならない。

_

 _FILE_ _

みなしソースファイル名(単純文字列リテラル)(

149

)

_

 _LINE_ _

現在のソース行の

(現在のソースファイルの中での)みなし行番号

(整

数定数)(

149

)

_

 _STDC_ _

整数定数 1。規格合致処理系であることを示すことを意図している。

_

 _STDC_HOSTED_ _

処理系が規格合致ホスト処理系の場合,整数定数 1。そうでない場合,

整数定数 0。

_

 _STDC_VERSION_ _

整数定数 199901L(

150

)

_

 _TIME_ _

前処理翻訳単位の翻訳の時刻(asctime 関数で生成される時刻と同

じ"hh:mm:ss"の形式の単純文字列リテラル)

。翻訳の時刻が得られ

ない場合,処理系定義の正しい時刻を提供しなければならない。

次に掲げる三つのマクロ名は,処理系がサポートする機能に従って定義される。

_

 _STDC_IEC_559_ _

附属書 FIEC 60559 浮動小数点演算)の規定に合致することを示す

ための整数定数 1。

_

 _STDC_IEC_559_COMPLEX_ _

附属書 GIEC 60559 互換複素数演算)の規定に合致することを示す

ための整数定数 1。

_

 _STDC_ISO_10646_ _

型 wchar_t の値が,ISO/IEC 10646(指定した年と月におけるすべ

ての附属書と技術に関する正誤表を含む)で定義された文字の符号化

表現をもつことを示すための(例えば 199712L のような)yyyymmL

の形式の整数定数。

(_  _LINE_  _及び_  _FILE_  _を除いた)あらかじめ定義されたマクロの値は,翻訳単位を通じて定数

のままとする。

これらのマクロ名及び識別子 defined は,#define 前処理指令又は#undef 前処理指令の対象にして

はならない。あらかじめ定義されたマクロ名を処理系が提供する場合は 1 文字目が下線,2 文字目が英大

文字,又は 1 文字目,2 文字目ともに下線,で始めなければならない。

処理系は,マクロ_ _cplusplus をあらかじめ定義してはならない。さらに,標準ヘッダの中で定義し

てもならない。

前方参照  asctime 関数(7.23.3.1),標準ヘッダ(7.1.2

6.10.9

プラグマ演算子

───────────────────────────────────────────────

(149)

みなしソースファイル名とみなし行番号は,#line 前処理指令を用いて変更することができる。

(150)

このマクロは,JIS X 3010:1993 では定義していなかった。JIS X 3010:1996 では,199409L と規定

していた。その意図は,今後も,この規格の改正ごとに増やし続けることにある。ただし,常に型

long int

の整数定数とする。


123

X 3010

:2003 (ISO/IEC 9899:1999)

     

意味規則  次の形式の単項演算子式

            _Pragma (

文字列リテラル    )

は,次に示す順で処理する。

−  文字列リテラルを

文字列解除(destringize)する。

−  L 接頭語があれば,それを削除

−  先頭と末尾の二重引用符を削除

−  逆斜線表記\"を二重引用符に置き換え

−  逆斜線表記\\を逆斜線一つに置き換え

−  文字列解除の結果の文字の並びを翻訳フェーズ(3)で処理し,前処理字句の列を生成する。

−  生成した前処理字句の列を,プラグマ指令の中の前処理字句列として実行する。

−  単項演算子式に最初にあった四つの前処理字句を削除する。

例  次の形式の指令

            #pragma listing on "..

\listing.dir"

は,次の形式でも表現できる。

            _Pragma ( "listing on

\"..\\listing.dir\"" )

後の形式は,このとおり書いてあった場合でも,次のようにマクロ置き換えの結果として生成さ

れた場合でも,同じように処理する。

           #define LISTING(x) PRAGMA(listing on #x)

      #define  PRAGMA(x)  _Pragma(#x)

      LISTING  (  ..

\listing.dir )

6.11

今後の言語の方針

6.11.1

浮動小数点型  今後の規格化により,long double よりも範囲,精度,又はその両方が大きい型

も含め,浮動小数点型を追加することがある。

6.11.2

識別子の結合  static 記憶域クラス指定子を使わずに,ファイル有効範囲で内部結合をもつ識別

子を宣言することは廃止予定事項とする。

6.11.3

外部名  外部名の有意性に対し,255 文字未満しか有意としない(各国際文字名又はソース拡張文

字は 1 文字と考える)制限は,廃止予定事項とする(既存の処理系に配慮して残した。

6.11.4

文字逆斜線表記  逆斜線表記としての英小文字は,今後の規格化のために予約済みとする。その他

の文字は,拡張のために使用してもよい。

6.11.5

記憶域クラス指定子  記憶域クラス指定子を宣言中の宣言指定子列の先頭以外の場所に置くこと

は,廃止予定事項とする。

6.11.6

関数宣言子  空の括弧を伴う関数宣言子(関数原型形式の仮引数型並びではない。)の使用は,廃

止予定事項とする。

6.11.7

関数定義  仮引数の識別子並びと宣言並びを別々に与える関数定義(関数原型形式の仮引数の型及

び識別子の宣言ではない。

)の使用は,廃止予定事項とする。

6.11.8

プラグマ指令  最初の前処理字句が STDC であるプラグマは,今後の規格化のために予約済みとす

る。

6.11.9

あらかじめ定義されたマクロ名  _ _STDC_  で始まるマクロ名は,今後の規格化のために予約済み

とする。


124

X 3010

:2003 (ISO/IEC 9899:1999)

     

7.

ライブラリ

7.1

概説

7.1.1

用語の定義  最初のナル文字で終わり,かつそれを含む連続した文字の並びを文字列(string)と

いう。用語

多バイト文字列(multibyte string)は,文字列中に含まれる多バイト文字に対して行う特別な処

理を強調するためか,又はワイド文字列との混同を避けるために使う。

文字列を指すポインタ(pointer to a

string

)は,その文字列の先頭の(最も低いアドレスをもつ)文字を指すポインタとする。

文字列の長さ(length

of a string

)は,ナル文字に先行するバイト数とし,

文字列の値(value of a string)は,それに含まれる文

字の値が順序どおりに並んだ値の列とする。

浮動小数点数を文字の並びに,又は逆に文字の並びを浮動小数点数に変換する関数が,文字の並びの中

で小数部の始まりを表すために使用する文字を,

小数点文字(decimal-point character)という(

151

)

。この規

格では,小数点文字をピリオドで表現するが,setlocale 関数を使用して変更してもよい。

コード値 0 のワイド文字を

ナルワイド文字(null wide character)という。

最初のナルワイド文字で終わり,

かつそれを含む連続したワイド文字の並びを

ワイド文字列(wide string)

という。

ワイド文字列を指すポインタ(pointer to a wide string)は,そのワイド文字列の先頭の(最も低い

アドレスをもつ)ワイド文字を指すポインタとする。

ワイド文字列の長さ(length of a wide string)は,ナ

ルワイド文字に先行するワイド文字の個数とし,

ワイド文字列の値(value of a wide string)は,それに含

まれるワイド文字のコード値が順序どおりに並んだ値の列とする。

多バイト文字列の中にあって,シフト状態を変化させる(可能性のある)連続するバイトの列を

シフト

シーケンス(shift sequence)という(5.2.1.2 参照)。シフトシーケンスは,対応するワイド文字をもっては

ならない。すなわち,シフトシーケンスは,それに隣接する多バイト文字に附属するものとみなす(

152

)

前方参照  setlocale 関数(7.11.1.1),文字操作(7.4

7.1.2

標準ヘッダ  各ライブラリ関数は,ヘッダ(header)(

153

)

において宣言する。関数の宣言には,関

数原型を含む型を用いる。ヘッダの内容は,#include 前処理指令を使って利用可能となる。ヘッダは,

関連する関数の集合を宣言し,加えてそれらに必要な型や関数の使用を容易にする付加的なマクロ定義も

含む。7.で規定する型の宣言は,この規格で明示的に異なる規定を行わない限り,型修飾子を含んではな

らない。

次に示すヘッダを,標準ヘッダとする。

<assert.h> <inttypes.h>

<signal.h> <stdlib.h>

<complex.h>

<iso646.h> <stdarg.h> <string.h>

 <ctype.h>

<limits.h>

<stdbool.h>

<tgmath.h>

───────────────────────────────────────────────

(151)

小数点文字を使用する関数は,数値変換関数(7.20.17.24.4.1)及び書式付き入出力関数(7.19.6

7.24.2

)である。

(152)

シフト状態に依存した表現形式では,MB_CUR_MAX 及び MB_LEN_MAX の値は,完全な多バイト文

字の最大バイト数に少なくとも一つの隣接するシフトシーケンスの最大長を加えた値以上でなけ

ればならない。二つ以上のシフトシーケンスを含めるかどうかは,処理系が選択する。

(153)

ヘッダは必ずしもソースファイルでなくてもよい。さらに,ヘッダ名における<及び>で囲まれた

列が必ずしも正しいソースファイル名である必要はない。


125

X 3010

:2003 (ISO/IEC 9899:1999)

     

<errno.h>  <locale.h> <stddef.h> <time.h>

<fenv.h> <math.h> <stdint.h>

<wchar.h>

<float.h> <setjmp.h>

<stdio.h> <wctype.h>

処理系の一部として提供するもの以外に,この箇条で規定する標準ヘッダの<及び>で囲まれた列のいず

れかと同じ名前のファイルが,

取り込まれるソースファイルを探索する標準の位置のいずれかにある場合,

その動作は未定義とする。

標準ヘッダはどのような順序で取り込んでもよい。各ヘッダは与えられた有効範囲内で 2 回以上取り込

んでもよいが,その効果は,<assert.h>の取込みの効果が NDEBUG の定義に依存すること(7.2 参照)

を除いて,1 回だけ取り込んだ場合と同じとする。ヘッダを使用する場合,ヘッダは外部宣言又は外部定

義の外側で取り込まなければならない。さらに,最初の取込みは,そのヘッダが宣言する関数若しくはオ

ブジェクト,又はヘッダが定義する型若しくはマクロに対する最初の参照よりも前に行わなければならな

い。しかし,同じ識別子を二つ以上のヘッダで宣言又は定義している場合,二つ目及びそれ以降の関連す

るヘッダは,その識別子に対する最初の参照の後に取り込んでもよい。プログラムは,取込みの前の時点

で定義されているキーワードと字句的に同一な名前のマクロをもってはならない。

7.

で規定するオブジェクト形式マクロの定義は,必要ならば括弧によって完全に保護されるコードに展

開されなければならない。それによって,任意の式の中で,そのオブジェクト形式マクロが単一の識別子

である場合と同じグループ分けをされる。

ライブラリ関数の宣言は,外部結合をもたなければならない。

標準ヘッダの内容の要約を

附属書 に記す。

前方参照  診断機能(7.2

7.1.3

予約済み識別子  各ヘッダは,関連する箇条で規定するすべての識別子を宣言又は定義する。関連

する今後のライブラリの方針の箇条で規定する識別子を,宣言又は定義してもよい。いかなる使用に対し

ても予約済みの識別子又はファイル有効範囲の識別子としての使用に対して予約済みの識別子を,宣言又

は定義してもよい。

−  下線に続き大文字 1 字又は下線に続きもう一つの下線で始まるすべての識別子は,いかなる使用に対

しても常に予約済みとする。

−  一つの下線で始まるすべての識別子は,通常の名前空間及びタグ名前空間の双方におけるファイル有

効範囲をもつ識別子としての使用に対して,常に予約済みとする。

−  7.(今後のライブラリの方針を含む。

)で規定する各マクロ名は,それに関連するヘッダのいずれかを

取り込んだ場合,この規格で明示的に異なる規定を行わない限り(7.1.4 参照)

,規定された使用法に

対して予約済みとする。

−  7.(今後のライブラリの方針を含む。

)で規定する外部結合をもつすべての識別子は,外部結合をもつ

識別子としての使用に対して常に予約済みとする(

154

)

−  7.(今後のライブラリの方針を含む。

)で規定するファイル有効範囲をもつ各識別子は,それに関連す

るヘッダのいずれかを取り込んだ場合,マクロ名としての使用に対して,及び,同じ名前空間におい

てファイル有効範囲をもつ識別子としての使用に対して予約済みとする。

───────────────────────────────────────────────

(154)

外部結合をもつ予約済み識別子には,errno,math_errhandling,setjmp 及び va_end など

がある。


126

X 3010

:2003 (ISO/IEC 9899:1999)

     

これ以外に予約済み識別子はない。プログラムが識別子を宣言又は定義し,その文脈においてその識別

子が予約済みである場合(7.1.4 で許されたもの以外)

,又は予約済みの識別子をマクロ名として定義する

場合,その動作は未定義とする。

プログラムが,下線に続き大文字 1 字又は下線に続きもう一つの下線で始まる識別子のマクロ定義を

(#undef によって)無効にした場合,その動作は未定義とする。

7.1.4

ライブラリ関数の使用法  明示的に異なる規定を行わない限り,次に規定する各規則を適用する。

−  関数の実引数が,正しくない値(関数の定義域外の値,プログラムのアドレス空間外を指すポインタ,

空ポインタ,

対応する仮引数が const 修飾されていない場合に変更不可な記憶域を指すポインタなど)

又は可変個数の実引数をもつ関数が期待しない型(既定の実引数拡張の後)をもつ場合,その動作は

未定義とする。

−  ある関数の実引数が配列であるとされている場合,その関数に実際に渡されるポインタは,すべての

アドレス計算及びオブジェクトへのアクセスが実際に有効となる値をもたなければならない(ポイン

タが配列の最初の要素を指す場合は有効となる。

−  あるヘッダ内で宣言する関数は,同じヘッダ内で定義する関数形式マクロとして追加して実装しても

よい。ヘッダを取り込むことによってあるライブラリ関数を明示的に宣言する場合,その宣言が,そ

のヘッダ内で定義された関数形式マクロに影響されないことを保証するために,次に示す二つの方法

のうちの一つを使うことができる。

−  関数のマクロ定義を局所的に無効にするためには,

(その名前の後ろに関数形式マクロの展開を

指示する左括弧が続かなくなるので)括弧で関数名を囲めばよい。同じ構文上の理由で,あるラ

イブラリ関数がマクロとしても定義されている場合でも,その関数のアドレスをとってもよい

(

155

)

−  #undef を使用してマクロ定義を無効にすれば,実際の関数への参照が保証される。

−  マクロとして実装されたライブラリ関数の呼出しでも,

その実引数がそれぞれただ 1 回だけ評価され,

かつ必要ならば括弧によって完全に保護されたコードに展開されなければならない(

156

)

。したがって,

実引数にどのような式を書いても,一般に問題はない。同様に,7.1.4 以降の箇条で規定する関数形式

マクロは,適合する返却値の型をもつ関数を呼び出すことができる式であれば,いかなる式からでも

───────────────────────────────────────────────

(155)

これは処理系があるライブラリ関数をマクロで提供した場合でも,実際の関数を提供しなければな

らないことを意味する。

(156)

このようなマクロは,対応する関数呼出しがもっている副作用完了点をもたないこともありうる。


127

X 3010

:2003 (ISO/IEC 9899:1999)

     

呼び出してよい(

157

)

−  整数定数式に展開するマクロとして掲げたすべてのオブジェクト形式マクロは,#if 前処理指令で使

用するためにも適していなければならない。

ヘッダ中で定義するいかなる型も参照することなくライブラリ関数を宣言できる場合,関連するヘッダ

を取り込まずにその関数を宣言してそれを使用してもよい。

ライブラリ関数が復帰する直前には,副作用完了点が存在する。

標準ライブラリの中の関数は,再入可能であることを保証しない。さらに,静的記憶域期間をもつオブ

ジェクトを変更してもよい(

158

)

例  関数 atoi は,次のいずれの方法で使用してもよい。

−  関連するヘッダを取り込んで使用する(マクロ展開になる可能性がある。

                #include <stdlib.h>

        const  char  *str;

        /*

... */

        i  =  atoi(str);

−  関連するヘッダを取り込んで使用する(本来の関数への参照になることが保証される。

                #include <stdlib.h>

        #undef  atoi

        const  char  *str;

        /*

... */

        i  =  atoi(str);

    又は,

           #include  <stdlib.h>

        const  char  *str;

        /*

... */

        i  =  (atoi)(str);

───────────────────────────────────────────────

(157)

下線で始まる外部識別子及びマクロ名は予約済みであるので,処理系は下線で始まる外部識別子及

びマクロ名に特別な意味を与えてもよい。例えば,識別子_BUILTIN_abs を,  abs 関数のインラ

インコードの生成を指示するために用いるようにしてもよい。その場合,コンパイラのコード生成

部がこの識別子を受け付ける処理系では,ヘッダに,

                #define abs(x) _BUILTIN_abs(x)

と記述することができる。

例えば,abs というライブラリ関数に対して,処理系のヘッダが abs のマクロを提供している

としても,組込み関数で実装しているとしても,それが本来の関数となることを保証したいユーザ

は,

                #undef abs

と書くとよい。その関数原型は,マクロ定義の前で宣言されるため,マクロ定義によって隠されて

いるが,これによって元の関数原型のほうが有効となる。

(158)

したがって,シグナル処理ルーチンは,一般に,標準ライブラリ関数を呼ぶことができない。


128

X 3010

:2003 (ISO/IEC 9899:1999)

     

−  明示的に宣言して使用する。

        extern  int  atoi(const  char  *);

        const  char  *str;

        /*

... */

        i  =  atoi(str);

7.2

診断機能<assert.h>  ヘッダ<assert.h>は,assert マクロを定義し,マクロ

                NDEBUG

を参照する。<assert.h>では NDEBUG を定義しない。ソースファイル中に<assert.h>を取り込む時点

で,NDEBUG がマクロ名として定義されている場合,assert マクロは単に,

              #define assert(ignore) ((void)0)

と定義する。assert マクロは,<assert.h>が取り込まれるごとに,その時点の NDEBUG の状態に従っ

て再定義される。

assert

マクロは,実際の関数としてではなくマクロとして実装しなければならない。実際の関数にア

クセスするためにマクロ定義を無効にした場合,その動作は未定義とする。

7.2.1

プログラム診断機能

7.2.1.1

assert

マクロ

形式

                #include <assert.h>

        void  assert(

スカラ型  expression);

機能  assert マクロは,プログラム中に診断機能を付け加える。assert マクロは,ボイド式に展開す

る。assert マクロを実行するとき,  expression(スカラ型をもたなければならない。

)が偽(すなわ

ち,0 と等しい。

)である場合,assert マクロは,偽の値をもたらした特定の呼出しに関する情報(情報

の中には,実引数のテキスト,ソースファイル名,ソース行番号及びその assert マクロの呼出しを字句

的に囲んでいる関数の名前を含む。後の三つはそれぞれマクロ_  _FILE_  _及び_  _LINE_  _の値,並びに

識別子_ _func_ _の値とする。

)を処理系定義の書式で標準エラーストリームに書き込む(

159

)

。さらに,そ

の後で abort 関数を呼び出す。

返却値  assert マクロは,値を返さない。

前方参照  abort 関数(7.20.4.1

7.3

複素数計算<complex.h>

7.3.1

複素数計算の概説  ヘッダ<complex.h>は,複素数計算をサポートする幾つかのマクロを定義し,

幾つかの関数を宣言する(

160

)

7.3 の各形式は,代表関数及びそれ以外の関数から成る関数群を規定する。

代表関数は,1 個以上の double complex の仮引数,及び double 又は double complex の返却値を

もつ。関数群の中の代表関数以外の関数は,代表関数の名前の最後に f を付けた名前の関数(float

complex

の仮引数,及び float 又は float complex の返却値をもつ。

,及び代表関数の名前の最後に

l

を付けた名前の関数(long double complex の仮引数,及び long double 又は long double

───────────────────────────────────────────────

(159)

出力するメッセージは,例えば,次のような形式になる。

Assertion failed :

実引数のテキスト, function  関数名, file  ファイル名, line  行番号

(160)

“今後のライブラリの方針”

7.26.1)参照。


129

X 3010

:2003 (ISO/IEC 9899:1999)

     

complex

の返却値をもつ。

)から成る。

マクロ

              complex

は,_Complex に展開し,マクロ

             _Complex_I

は,虚数単位の値をもつ型 const float _Complex の定数式に展開する(

161

)

マクロ

              imaginary

及びマクロ

              _Imaginary_I

は,処理系が虚数型をサポートする場合,そしてその場合に限り,定義する(

162

)

。それらを定義する場合,

imaginary

は,_Imaginary に展開し,_Imaginary_I は,虚数単位の値をもつ型 const float

_Imaginary

の定数式に展開する。

マクロ

              I

は,_Imaginary_I 又は_Complex_I に展開する。_Imaginary_I が定義されていない場合,I は

_Complex_I

に展開しなければならない。

7.1.3

の規定にかかわらず,プログラムは,マクロ complex,imaginary,及び I を無効にしてもよく,

更に再定義してもよい。

前方参照  IEC 60559 に適合する複素数計算(附属書 G

7.3.2

複素数計算の規約  値は,度ではなく,ラジアンで解釈する。処理系は,errno を設定してもよ

いが,必ずしも設定する必要はない。

7.3.3

分岐切断線  7.3 で規定する幾つかの関数は,それをまたぐと関数が不連続となる分岐切断線をも

つ。符号付き 0 をもつ処理系(すべての IEC 60559 の実装を含んでいる。

)では(その処理系は,

附属書 G

の規定に従う。

,切断線を境とする片側と別の片側とを 0 の符号で区別する。これによって,切断線を境

とするいずれの側から切断線に接近しても,

その関数は,

連続になる

(内部表現形式上の制限は別として。

例えば,平方根関数は,負の実軸に沿って分岐切断線をもっており,切断線の上側,すなわち虚部が+0 を

もつ側は,正の虚軸に写像し,切断線の下側,すなわち虚部が

0

をもつ側は,負の虚軸に写像する。

符号付き 0 をサポートしない処理系は(

附属書 参照),分岐切断線を境とする両側を区別することが

できない。符号付き 0 をサポートしない処理系は,切断線の有限な終点のまわりを反時計方向から切断線

に近づくと関数が連続となるように切断線を写像しなければならない。

7.3 で規定する関数に対する分岐

切断線は,ちょうど 1 個の有限な終点しかもたない。

)例えば,平方根関数は,負の実軸に沿っている切断

線の有限な終点のまわりを反時計方向に進むと,切断線に上側から近づくので,切断線は,正の虚軸に写

像する。

7.3.4

CX_LIMITED_RANGE

プラグマ

形式

───────────────────────────────────────────────

(161)

虚数単位は,

i

2

=

1

となる数

i

である。

(162)

虚数型の仕様は,

附属書 G(参考)にある。


130

X 3010

:2003 (ISO/IEC 9899:1999)

     

                #include <complex.h>

        #pragma  STDC  CX_LIMITED_RANGE

状態切替え指定

機能  複素数の乗算,除算,及び絶対値に対する通常の数学公式は,無限大の扱い,並びに不必要なオー

バフロー及びアンダフローのために,問題が多い。CX_LIMITED_RANGE プラグマは,

(状態が“オン”の

場合)通常の数学公式が適用可能であることを処理系に知らせる目的で使用できる(

163

)

。このプラグマは,

外部宣言の外側か,又は複合文の中のすべての明示的な宣言及び文の前で,用いることができる。外部宣

言の外側で用いる場合,このプラグマは,それが出現した時点から,他の CX_LIMITED_RANGE プラグマ

が出現するまで,又は翻訳単位の終わりまで,有効とする。複合文の内側で用いる場合,このプラグマは,

それが出現した時点から他の CX_LIMITED_RANGE プラグマが出現するまで(入れ子になった複合文も含

む。

,又はその複合文の最後まで有効とする。複合文の終わりでは,このプラグマに対する状態は,その

複合文に入る直前の状態に戻る。このプラグマをこれら以外の文脈で使った場合,その動作は未定義とす

る。このプラグマに対する既定の状態は,

“オフ”とする。

7.3.5

複素数三角関数

7.3.5.1

cacos

関数群

形式

               #include  <complex.h>

        double  complex  cacos(double  complex  z);

        float  complex  cacosf(float  complex  z);

        long  double  complex  cacosl(long  double  complex  z);

機能  cacos 関数群は,z の複素数逆余弦を計算する。cacos 関数群は,区間[

1,+1]

の外側に,実軸に沿

って分岐切断線をもつ。

返却値  cacos 関数群は,虚軸方向には数学的に無限の区間,実軸方向には区間[0,+

π

]

を値域とする複素

数逆余弦値を返す。

7.3.5.2

casin

関数群

形式

                #include <complex.h>

        double  complex  casin(double  complex  z);

        float  complex  casinf(float  complex  z);

        long  double  complex  casinl(long  double  complex  z);

機能  casin 関数群は,z の複素数逆正弦を計算する。casin 関数群は,区間[

1,+1]

の外側に,実軸に沿

って分岐切断線をもつ。

返却値  casin 関数群は,虚軸方向には数学的に無限の区間,実軸方向には区間[

−π

/2,+

π

/2]

を値域とす

───────────────────────────────────────────────

(163)

このプラグマの目的は,プログラマが次の公式が安全だと判定できる場合,それを処理系に知らせ

ることである。

                (

x

+

iy

)

×(

u

+

iv

) = (

xu

yv

) +

i

(

yu

+

xv

)

                (

x

+

iy

) / (

u

+

iv

) = [(

xu

+

yv

) +

i

(

yu

xv

)] / (

u

2

+

v

2

)

                |

x

+

iy 

| =

2

2

y

x

+


131

X 3010

:2003 (ISO/IEC 9899:1999)

     

る複素数逆正弦値を返す。

7.3.5.3

catan

関数群

形式

                #include <complex.h>

        double  complex  catan(double  complex  z);

        float  complex  catanf(float  complex  z);

        long  double  complex  catanl(long  double  complex  z);

機能  catan 関数群は,z の複素数逆正接を計算する。catan 関数群は,区間[

i

,+

i

]

の外側に,虚軸に沿

って分岐切断線をもつ。

返却値  catan 関数群は,虚軸方向には数学的に無限の区間,実軸方向には区間[

−π

/2,+

π

/2]

を値域とす

る複素数逆正接値を返す。

7.3.5.4

ccos

関数群

形式

                #include <complex.h>

        double  complex  ccos(double  complex  z);

        float  complex  ccosf(float  complex  z);

        long  double  complex  ccosl(long  double  complex  z);

機能  ccos 関数群は,z の複素数余弦を計算する。

返却値  ccos 関数群は,複素数余弦値を返す。

7.3.5.5

csin

関数群

形式

               #include  <complex.h>

        double  complex  csin(double  complex  z);

        float  complex  csinf(float  complex  z);

        long  double  complex  csinl(long  double  complex  z);

機能  csin 関数群は,z の複素数正弦を計算する。

返却値  csin 関数群は,複素数正弦値を返す。

7.3.5.6

ctan

関数群

形式

               #include  <complex.h>

        double  complex  ctan(double  complex  z);

        float  complex  ctanf(float  complex  z);

        long  double  complex  ctanl(long  double  complex  z);

機能  ctan 関数群は,z の複素数正接を計算する。

返却値  ctan 関数群は,複素数正接値を返す。

7.3.6

複素数双曲線関数

7.3.6.1

cacosh

関数群

形式

               #include  <complex.h>

        double  complex  cacosh(double  complex  z);


132

X 3010

:2003 (ISO/IEC 9899:1999)

     

        float  complex  cacoshf(float  complex  z);

        long  double  complex  cacoshl(long  double  complex  z);

機能  cacosh 関数群は,z の複素数逆双曲線余弦を計算する。cacosh 関数群は,値が 1 未満の範囲で,

実軸に沿って分岐切断線をもつ。

返却値  cacosh 関数群は,実軸方向には非負である半区間,虚軸方向には区間[

iπ

,+

i

π

]

を値域とする複

素数逆双曲線余弦値を返す。

7.3.6.2

casinh

関数群

形式

                #include <complex.h>

        double  complex  casinh(double  complex  z);

        float  complex  casinhf(float  complex  z);

        long  double  complex  casinhl(long  double  complex  z);

機能  casinh 関数群は,z の複素数逆双曲線正弦を計算する。casinh 関数群は,区間[

i

,+

i

]

の外側に,

虚軸に沿って分岐切断線をもつ。

返却値  casinh 関数群は,実軸方向には数学的に無限の区間,虚軸方向には区間[

iπ

/2,+

i

π

/2]

を値域と

する複素数逆双曲線正弦値を返す。

7.3.6.3

catanh

関数群

形式

               #include  <complex.h>

        double  complex  catanh(double  complex  z);

        float  complex  catanhf(float  complex  z);

        long  double  complex  catanhl(long  double  complex  z);

機能  catanh 関数群は,z の複素数逆双曲線正接を計算する。catanh 関数群は,区間[

1,+1]

の外側に,

実軸に沿って分岐切断線をもつ。

返却値  catanh 関数群は,実軸方向には数学的に無限の区間,虚軸方向には区間[

iπ

/2,+

i

π

/2]

を値域と

する複素数逆双曲線正接値を返す。

7.3.6.4

ccosh

関数群

形式

               #include  <complex.h>

        double  complex  ccosh(double  complex  z);

        float  complex  ccoshf(float  complex  z);

        long  double  complex  ccoshl(long  double  complex  z);

機能  ccosh 関数群は,z の複素数双曲線余弦を計算する。

返却値  ccosh 関数群は,複素数双曲線余弦値を返す。

7.3.6.5

csinh

関数群

形式

                #include <complex.h>

        double  complex  csinh(double  complex  z);

        float  complex  csinhf(float  complex  z);

        long  double  complex  csinhl(long  double  complex  z);


133

X 3010

:2003 (ISO/IEC 9899:1999)

     

機能  csinh 関数群は,z の複素数双曲線正弦を計算する。

返却値  csinh 関数群は,複素数双曲線正弦値を返す。

7.3.6.6

ctanh

関数群

形式

                #include <complex.h>

        double  complex  ctanh(double  complex  z);

        float  complex  ctanhf(float  complex  z);

        long  double  complex  ctanhl(long  double  complex  z);

機能  ctanh 関数群は,z の複素数双曲線正接を計算する。

返却値  ctanh 関数群は,複素数双曲線正接値を返す。

7.3.7

複素数指数関数及び複素数対数関数

7.3.7.1

cexp

関数群

形式

                #include <complex.h>

        double  complex  cexp(double  complex  z);

        float  complex  cexpf(float  complex  z);

        long  double  complex  cexpl(long  double  complex  z);

機能  cexp 関数群は,自然対数の底

e

の z 乗(指数は複素数)を計算する。

返却値  cexp 関数群は,

e

を基数とする複素数指数関数値を返す。

7.3.7.2

clog

関数群

形式

               #include  <complex.h>

        double  complex  clog(double  complex  z);

        float  complex  clogf(float  complex  z);

        long  double  complex  clogl(long  double  complex  z);

機能  clog 関数群は,z の複素数自然対数(

e

を底とする)を計算する。clog 関数群は,負の実軸に沿

って分岐切断線をもつ。

返却値  clog 関数群は,実軸方向には数学的に無限の区間,虚軸方向には区間[

iπ

,+

i

π

]

を値域とする複

素数自然対数値を返す。

7.3.8

複素数べき乗関数及び複素数絶対値関数

7.3.8.1

cabs

関数群

形式

               #include  <complex.h>

        double  cabs(double  complex  z);

        float  cabsf(float  complex  z);

        long  double  cabsl(long  double  complex  z);

機能  cabs 関数群は,z の複素数絶対値[規数(norm),モジュラス(modulus),又は大きさ(magnitude)

ともいう。

]を計算する。

返却値  cabs 関数群は,複素数絶対値を返す。

7.3.8.2

cpow

関数群


134

X 3010

:2003 (ISO/IEC 9899:1999)

     

形式

                #include <complex.h>

        double complex cpow(double complex x, double complex y);

        float complex cpowf(float complex x, float complex y);

        long double complex cpowl(long double complex x, long double complex y);

機能  cpow 関数群は,複素数べき乗関数 x

y

を計算する。cpow 関数群は,負の実軸に沿って,第 1 仮引

数に対する分岐切断線をもつ。

返却値  cpow 関数群は,複素数べき乗関数値を返す。

7.3.8.3

csqrt

関数群

形式

               #include  <complex.h>

        double  complex  csqrt(double  complex  z);

        float  complex  csqrtf(float  complex  z);

                long double complex csqrtl(long double complex z);

機能  csqrt 関数群は,z の複素数平方根を計算する。csqrt 関数群は,負の実軸に沿って分岐切断線を

もつ。

返却値  csqrt 関数群は,右半平面(虚軸を含む。)を値域とする複素数平方根値を返す。

7.3.9

複素数操作関数

7.3.9.1

carg

関数群

形式

               #include  <complex.h>

        double  carg(double  complex  z);

        float  cargf(float  complex  z);

        long  double  cargl(long  double  complex  z);

機能  carg 関数群は,z の偏角(argument)[位相角(phase angle)ともいう。]を計算する。carg 関数

群は,負の実軸に沿って分岐切断線をもつ。

返却値  carg 関数群は,区間[

−π

,+

π

]

を値域とする偏角の値を返す。

7.3.9.2

cimag

関数群

形式

                #include <complex.h>

        double  cimag(double  complex  z);

        float  cimagf(float  complex  z);

        long  double  cimagl(long  double  complex  z);

機能  cimag 関数群は,z の虚部を計算する(

164

)

返却値  cimag 関数群は,虚部の値を返す(実数として)。

7.3.9.3

conj

関数群

形式

───────────────────────────────────────────────

(164)

複素数型の変数 z に対して,z == creal(z) + cimag(z)*I となる。


135

X 3010

:2003 (ISO/IEC 9899:1999)

     

                #include <complex.h>

        double  complex  conj(double  complex  z);

        float  complex  conjf(float  complex  z);

        long  double  complex  conjl(long  double  complex  z);

機能  conj 関数群は,z の虚部の符号を反転させて複素共役を計算する。

返却値  conj 関数群は,複素共役の値を返す。

7.3.9.4

cproj

関数群

形式

                #include <complex.h>

        double  complex  cproj(double  complex  z);

        float  complex  cprojf(float  complex  z);

        long  double  complex  cprojl(long  double  complex  z);

機能  cproj 関数群は,リーマン球面上への z の射影(projection)を計算する。すなわち,z が複素平面

上のすべての無限遠点(たとえ,実部又は虚部の一方が無限大であり,他方が NaN であっても)の場合,

実軸上の正の無限大に射影し,それ以外の場合,z 自身に射影する。z の実部又は虚部が無限大である場

合,cproj(z)は,

               Infinity + I * copysign(0.0, cimag(z))

と等しい。

返却値  cproj 関数群は,リーマン球面上への射影の値を返す。

7.3.9.5

creal

関数群

形式

             #include  <complex.h>

       double  creal(double  complex  z);

       float  crealf(float  complex  z);

       long  double  creall(long  double  complex  z);

機能  creal 関数群は,z の実部を計算する(

165

)

返却値  creal 関数群は,実部の値を返す。

7.4

文字操作<ctype.h>  ヘッダ<ctype.h>は,文字の分類及び文字の変換に有用な幾つかの関数を宣

言する(

166

)

。この中で宣言されるすべての関数は,int 型の一つの実引数をもつ。その値は unsigned

char

で表現可能であるか,又はマクロ EOF の値に等しくなければならない。実引数がその他の値をもつ

場合,その動作は未定義とする。

これらの関数の動作は,その時点のロケールによって影響を受ける。"C"ロケールでない場合に限って

適用される文化圏固有の側面をもつ関数については,それぞれの箇条で規定する。

表示文字(printing character)は,表示装置上で一つの表示位置を占める文字から成る文化圏固有の文字

集合の要素をいう。

制御文字(control character)は,表示文字以外の文字から成る文化圏固有の文字集合

───────────────────────────────────────────────

(165)

複素数型の変数 z に対して,z == creal(z) + cimag(z)*I となる。

(166)

“今後のライブラリの方針”

7.26.2)参照。


136

X 3010

:2003 (ISO/IEC 9899:1999)

     

の要素をいう(

167

)

。すべての英字及び数字は,表示文字とする。

前方参照  EOF(7.19.1),文化圏固有操作(7.11

7.4.1

文字種分類関数  この箇条の関数は,実引数 c の値がその関数の機能の項で規定するとおりの値で

ある場合,そしてその場合に限り,0 以外の値(真)を返す。

7.4.1.1

isalnum

関数

形式

          #include  <ctype.h>

        int  isalnum(int  c);

機能  isalnum 関数は,isalpha 又は isdigit が真となる文字かどうかを判定する。

7.4.1.2

isalpha

関数

形式

                #include <ctype.h>

        int  isalpha(int  c);

機能  isalpha 関数は,isupper 若しくは islower が真となる文字,又は iscntrl,isdigit,ispunct

若しくは isspace のいずれも真とならない文化圏固有のアルファベット文字集合の中の文字かどうかを

判定する(

168

)

。"C"ロケールでは,isalpha は,isupper 又は islower が真となる文字に対してだけ真

を返す。

7.4.1.3

isblank

関数

形式

               #include  <ctype.h>

        int  isblank(int  c);

機能  isblank 関数は,標準ブランク文字のいずれかの文字,又は isspace が真となりテキスト中の行

の中の語を区切るために使う文化圏固有の文字集合の中の文字かどうかを判定する。

標準ブランク文字は,

空白(' ')及び水平タブ('\t')とする。"C"ロケールでは,isblank は,標準ブランク文字に対して

だけ真を返す。

7.4.1.4

iscntrl

関数

形式

              #include  <ctype.h>

        int  iscntrl(int  c);

機能  iscntrl 関数は,制御文字かどうかを判定する。

7.4.1.5

isdigit

関数

形式

               #include  <ctype.h>

───────────────────────────────────────────────

(167)

JIS X 0201

の 7 ビット符号化文字集合を使用する処理系では,表示文字は,その値が 0x20[文字

SPACE

(スペース)

]から 0x7E(オーバライン)までにある文字である。一方,制御文字は,その

値が,0(NUL)から 0x1F(IS1)までにある文字,及び文字 0x7F[文字 DELETE(抹消)

]である。

(168)

関数 islower 及び isupper は,付加的なこれらの文字のそれぞれに対して,独立に真か偽かを

判定する。したがって,四つの値の組合せのすべてが可能である。


137

X 3010

:2003 (ISO/IEC 9899:1999)

     

        int  isdigit(int  c);

機能  isdigit 関数は,10 進数字(5.2.1 で定義)かどうかを判定する。

7.4.1.6

isgraph

関数

形式

        #include  <ctype.h>

        int  isgraph(int  c);

機能  isgraph 関数は,空白(' ')を除く表示文字かどうかを判定する。

7.4.1.7

islower

関数

形式

            #include  <ctype.h>

        int  islower(int  c);

機能  islower 関数は,小文字,又は iscntrl,isdigit,ispunct 若しくは isspace のいずれも真

とならない文化圏固有の文字集合の中の文字かどうかを判定する。"C"ロケールでは,islower は,小文

字(5.2.1 で定義)に対してだけ真を返す。

7.4.1.8

isprint

関数

形式

              #include  <ctype.h>

        int  isprint(int  c);

機能  isprint 関数は,表示文字[空白(' ')を含む。]かどうかを判定する。

7.4.1.9

ispunct

関数

形式

              #include  <ctype.h>

        int  ispunct(int  c);

機能  ispunct 関数は,isspace 又は isalnum のいずれも真とならない文化圏固有の区切り文字集合

の中の表示文字かどうかを判定する。"C"ロケールでは,ispunct は,isspace 又は isalnum のいずれ

も真とならないすべての表示文字に対して真を返す。

7.4.1.10

  isspace

関数

形式

               #include  <ctype.h>

        int  isspace(int  c);

機能  isspace 関数は,標準空白類文字のいずれかの文字,又は isalnum が偽となる文化圏固有の文字

集合の中の一つの文字かどうかを判定する。標準空白類文字は,空白(' ')

,書式送り('\f')

,改行

('\n')

,復帰('\r')

,水平タブ('\t')及び垂直タブ('\v')とする。"C"ロケールでは,isspace

は,標準空白類文字に対してだけ真を返す。

7.4.1.11

  isupper

関数

形式

          #include  <ctype.h>

        int  isupper(int  c);

機能  isupper 関数は,大文字,又は iscntrl,isdigit,ispunct 若しくは isspace のいずれも真

とならない文化圏固有の文字集合の中の文字かどうかを判定する。"C"ロケールでは,isupper は,大文


138

X 3010

:2003 (ISO/IEC 9899:1999)

     

字(5.2.1 で定義)に対してだけ真を返す。

7.4.1.12

  isxdigit

関数

形式

                #include <ctype.h>

        int  isxdigit(int  c);

機能  isxdigit 関数は,16 進数字(6.4.4.1 で定義)かどうかを判定する。

7.4.2

大文字小文字変換関数

7.4.2.1

tolower

関数

形式

               #include  <ctype.h>

        int  tolower(int  c);

機能  tolower 関数は,大文字を対応する小文字に変換する。

返却値  実引数が,isupper 関数に対して真となる文字であって,かつ islower 関数が真となる 1 個以

上の対応する文字(その時点のロケールの指定に従う。

)がある場合,tolower 関数はその対応する文字

のいずれか一つを返す(同じロケールに対しては必ず同じ文字。

。そうでない場合,その実引数を変換せ

ずにそのまま返す。

7.4.2.2

toupper

関数

形式

        #include  <ctype.h>

        int  toupper(int  c);

機能  toupper 関数は,小文字を対応する大文字に変換する。

返却値  実引数が,islower 関数に対して真となる文字であって,かつ isupper 関数が真となる 1 個以

上の対応する文字(その時点のロケールの指定に従う。

)がある場合,toupper 関数はその対応する文字

のいずれか一つを返す(同じロケールに対しては必ず同じ文字。

。そうでない場合,その実引数を変換せ

ずにそのまま返す。

7.5

エラー<errno.h>  ヘッダ<errno.h>は,エラー条件の報告に関連する幾つかのマクロを定義する。

定義するマクロは,EDOM,EILSEQ,ERANGE 及び errno とする。

        EDOM

        EILSEQ

        ERANGE

は,それぞれ区別可能な正の値をもつ型 int の整数定数式に展開する。これら三つのマクロは,#if 前処

理指令で使用するために適している。

                errno

は,型 int をもつ変更可能な左辺値(

169

)

に展開する。幾つかのライブラリ関数がその値を正のエラー番号

に設定する。errno をマクロとするか又は外部結合で宣言された識別子とするかは,未規定とする。実際

のオブジェクトにアクセスするためにマクロ定義を無効にした場合,

又はプログラムが名前 errno をもつ

───────────────────────────────────────────────

(169)

マクロ errno は,

オブジェクトの識別子である必要はない。

それは関数呼出し

(例えば,

*errno()

によって得られる変更可能な左辺値に展開してもよい。


139

X 3010

:2003 (ISO/IEC 9899:1999)

     

識別子を定義した場合,その動作は未定義とする。

プログラム開始時に,errno の値は 0 とし,いかなるライブラリ関数も 0 には設定しない(

170

)

。この規

格の関数の機能の項で errno の使用について規定していない場合,エラーのあるなしにかかわらず,ライ

ブラリ関数の呼出しによって errno の値を 0 以外に設定してもよい。

処理系は,E に続き数字 1 字又は E に続き大文字 1 字(

171

)

で始まるマクロ定義を追加してもよい。

7.6

浮動小数点環境<fenv.h>  ヘッダ<fenv.h>は,浮動小数点環境(floating-point environment)への

アクセス手段を提供するための二つの型,幾つかのマクロ及び幾つかの関数を宣言する。浮動小数点環境

は,処理系がサポートする何種類かの浮動小数点状態フラグ及び何種類かの浮動小数点制御モードの総称

とする(

172

)

浮動小数点状態フラグ(floating-point status flag)は,浮動小数点例外(floating-point exception)

(補助的な情報を提供するために例外的な浮動小数点算術の副作用として起きる。

が生成された時に値を

セットする(ただし,決してクリアしない)システム変数とする。

浮動小数点制御モード(floating-point

control mode

)は,利用者が値を設定してもよいシステム変数とし,その値を設定した後の浮動小数点算術

の動作に影響を与える。

次に掲げる三つのプログラム上の規約は,浮動小数点環境に対してこの規格が意図しているモデルをサ

ポートする(

173

)

−  関数呼出しは,その呼出し元の浮動小数点制御モードを変えることはなく,その呼出し元の浮動小数

点状態フラグをクリアすることもなく,また,その呼出し元の浮動小数点状態フラグの状態に依存す

ることもない(これと異なる規約が文書化されていない限りは。

−  関数呼出しは,既定の浮動小数点制御モードを要求することを仮定する(要求しないことが文書化さ

れていない限りは。

−  関数呼出しは,浮動小数点例外を生成するという可能性があることを仮定する(可能性がないことが

文書化されていない限りは。

              fenv_t

は,浮動小数点環境全体を表す。

             fexcept_t

───────────────────────────────────────────────

(170)

したがって,エラー検査のために errno を使用するプログラムは,ライブラリ関数呼出しの前に

errno

の値を 0 に設定し,その次のライブラリ関数の呼出しの前にその値を検査すべきである。

もちろん,ライブラリ関数は,関数の入口で errno の値を保存した後に 0 に設定し,関数が復帰

する直前まで errno の値が 0 のままの場合,元の値に戻すということも可能である。

(171)

“今後のライブラリの方針”

7.26.3)参照。

(172)

このヘッダは,IEC 60559 によって要求される浮動小数点例外の状態を示すフラグ及び丸め方向モ

ード,及びその他の同様な浮動小数点の状態を示す情報をサポートするために設計された。さらに,

すべてのシステムでのコードの可搬性を促進するために設計された。

(173)

これらの規約によって,プログラマは,既定の浮動小数点制御モードを安全に仮定することができ

る(又は,それらを意識する必要がなくなる。

。浮動小数点環境へアクセスすることに関しては,

明示的にそれを行っているプログラマ又はプログラムが責任を負う。


140

X 3010

:2003 (ISO/IEC 9899:1999)

     

は,浮動小数点状態フラグを集合的に表す(処理系がそのフラグに関連付けている状態すべてを含む。

マクロ

               FE_DIVBYZERO

        FE_INEXACT

        FE_INVALID

        FE_OVERFLOW

        FE_UNDERFLOW

のそれぞれは,処理系が 7.6.2 で規定する関数を使って浮動小数点例外をサポートする場合,そしてその場

合に限り,定義する(

173a

)

。処理系は,上に掲げた五つのマクロ以外に,処理系定義の浮動小数点例外を,

FE_

とそれに続く大文字 1 字で始まる名前をもつマクロ定義で規定してもよい。定義されたマクロは,整

数定数式に展開する。その値は,これらマクロのあらゆる組合せについて,ビット単位の論理和の結果が

すべて異なる値となる。

マクロ

        FE_ALL_EXCEPT

は,処理系が定義するすべての浮動小数点例外マクロの単なるビット単位の論理和とする。

マクロ

        FE_DOWNWARD

        FE_TONEAREST

        FE_TOWARDZERO

        FE_UPWARD

のそれぞれは,処理系が fegetround 関数によって丸めの方向を取得し,fesetround 関数によって丸

めの方向を設定することをサポートする場合,そしてその場合に限り,定義する。処理系は,上に掲げた

四つのマクロ以外に,処理系定義の丸めの方向を,FE_とそれに続く大文字 1 字で始まる名前をもつマク

ロ定義で規定してもよい。定義されたマクロは,それぞれ異なる非負の値をもつ整数定数式に展開する(

174

)

マクロ

        FE_DFL_ENV

は,プログラムの既定の浮動小数点環境(プログラム開始処理で設定される。

)を表し,型“const 修飾さ

れた fenv_t へのポインタ”をもつ。マクロ FE_DFL_ENV は,<fenv.h>で規定する浮動小数点環境を管

理する関数の実引数として使用できる。

処理系は,マクロ FE_DFL_ENV 以外に,処理系定義の環境を,FE_とそれに続く大文字 1 字で始まる名

前をもち,型“const 修飾された fenv_t へのポインタ”をもつマクロ定義で規定してもよい。

7.6.1

FENV_ACCESS

プラグマ

形式

───────────────────────────────────────────────

(173a)  7.6.2

の関数の少なくとも一つについて,このマクロを適切な実引数として使用した関数呼出しが

成功する状況があれば,処理系は例外をサポートしているとみなされる。7.6.2 のすべての関数の

呼出しが常に成功する必要はない。

(174)

丸め方向マクロを FLT_ROUNDS の値に対応する定数に展開してもよい。しかし,丸め方向マクロ

をそのように展開することは要求されていない。


141

X 3010

:2003 (ISO/IEC 9899:1999)

     

        #include  <fenv.h>

        #pragma  STDC  FENV_ACCESS

状態切替え指定

機能  FENV_ACCESS プラグマは,プログラムが浮動小数点状態フラグを判定するために浮動小数点環境

にアクセスするかもしれない場合,又は,プログラムが既定状態以外の浮動小数点制御モードの下で走行

するかもしれない場合,処理系にその情報を伝える手段を提供する(

175

)

。このプラグマは,外部宣言の外

側か,又は複合文の中のすべての明示的な宣言及び文の前のいずれかの場所に現れなければならない。外

部宣言の外側に現れる場合,このプラグマは,それが出現した時点から,別の FENV_ACCESS が出現する

まで,又は翻訳単位の最後まで有効とする。複合文の中に現れる場合,このプラグマは,それが出現した

時点から別の FENV_ACCESS プラグマが出現するまで(入れ子になった複合文も含む。

)又はその複合文

の最後まで有効とする。複合文の最後で,このプラグマに対する状態は,その複合文に入る直前の状態に

戻る。このプラグマをこれら以外の文脈で使った場合,その動作は未定義とする。プログラムの一部が,

浮動小数点状態フラグを判定するか,浮動小数点制御モードを設定するか,又は既定状態以外のモード設

定の下で走行する場合で,かつ,FENV_ACCESS プラグマに対する状態が“オフ”で翻訳されている場合,

その動作は未定義とする。このプラグマに対する既定の状態(

“オン”又は“オフ”

)は,処理系定義とす

る。

(FENV_ACCESS“オフ”で翻訳されたプログラムの部分から,FENV_ACCESS“オン”で翻訳された

プログラムの部分に実行が移る場合,浮動小数点状態フラグの状態は,未規定とし,浮動小数点制御モー

ドは,既定の設定をもつ。

        #include  <fenv.h>

        void  f(double  x)

        {

                #pragma  STDC  FENV_ACCESS  ON

                void  g(double);

                void  h(double);

                /*

... */

                g(x  +  1);

                h(x  +  1);

                /*

... */

        }

  関数 g が,最初の x + 1 の副作用としてセットされる状態フラグに依存するかもしれない場

合,又は,2 番目の x + 1 が,関数 g の呼出しの副作用として設定される制御モードに依存する

かもしれない場合,そのプログラムの適切な位置に#pragma STDC FENV_ACCESS ON を置かな

───────────────────────────────────────────────

(175)

FENV_ACCESS

プラグマの目的は,フラグの判定及びモードの変更を無効にするかもしれない何ら

かの最適化を可能にすることである(例えば,広域的な共通部分式の削除,コード移動,定数のた

たみ込みなど。

。一般的に,FENV_ACCESS の状態が“オフ”の場合,翻訳プログラムは,既定の

モードが有効になっており,かつそのフラグは判定されることがない,と仮定することができる。