IAR C言語拡張
コンパイラには、幅広いC言語拡張セットが用意されています。アプリケーションで必要な拡張が簡単に見つかるように、このセクションでは拡張は以下のようにグループ化されています。
組み込みシステムプログラミングのための拡張 — 一般的にメモリの制限を満たすために、使用する特定のコアでの効率的な組み込みプログラミングに特化した拡張。
C規格に対する緩和 — つまり、C規格の重要でない問題の緩和や、便利ではあるが小規模な構文の拡張。標準Cに対する緩和を参照してください。
組み込みシステムプログラミングのための拡張
以下の言語拡張は、CとC++の両方のプログラミング言語で使用可能なもので、組み込みシステムのプログラミングに適しています。
Type attributes and object attributes
関連する概念、一般的な構文規則、リファレンス情報については、「拡張キーワード」を参照してください。
絶対アドレスあるいは指定セクションへの配置
@演算子や#pragmalocationディレクティブを使用して、グローバル変数や静的変数を絶対アドレスに配置することや、変数や関数を指定されたセクションに配置することができます。これらの機能の使用方法については、データと関数のメモリ配置制御、locationを参照してください。アライメントの制御
各データタイプには、それ自身のアライメントがあります。詳細については、アライメントを参照してください。アライメントを変更したい場合は、
__packedデータ型属性、#pragma packディレクティブおよび#pragma data_alignmentディレクティブが利用可能です。オブジェクトのアライメントをチェックする場合は、__ALIGNOF__()演算子を使用します。__ALIGNOF__演算子は、オブジェクトのアライメントの取得に使用できます。以下の2つのフォーマットのいずれかで指定します。__ALIGNOF__(type)__ALIGNOF__(expression)
2番目のフォーマットのexpressionは評価されません。
標準Cファイル
stdalign.hも参照してください。ビットフィールドと非標準型
標準のCでは、ビットフィールドの型は
intかunsigned intでなければなりません。IAR Cの言語拡張を使用することで、任意の整数型や列挙型を使用できます。これには、場合によって構造体のサイズが小さくなるという利点があります。詳細については、ビットフィールドを参照してください。
専用セクション演算子
コンパイラは、以下のビルトインセクション演算子を使用して、開始アドレスや終了アドレス、セクションの取得をサポートします。
| 指定のセクションまたはブロックの最初のバイトアドレスを返します。 |
| 指定のセクションまたはブロックの後の最初のアドレスバイトを返します。 |
| 指定のセクションまたはブロックのサイズ(バイト)を返します。 |
注記
エイリアス、__segment_begin/__sfb、__segment_end/__sfe、__segment_size/__sfsも使用できます。
これらの演算子は、リンカ設定ファイルで定義された指定のセクションまたは指定ブロック上で使用できます。
これらの演算子は構文的に以下のように宣言された場合と同じように動作します。
void * __section_begin(char const *section) void * __section_end(char const *section) size_t __section_size(char const *section)
@演算子または#pragma locationディレクティブを使用してデータオブジェクトや関数をユーザ定義のセクションに配置したり、指定ブロックをリンカ設定ファイルで使用したりする場合、セクション演算子を使用して、セクションまたはブロックが配置されたメモリ範囲の開始アドレスと終了アドレスを取得することができます。
The named セクション must be a string literal and it must have been declared earlier with the #pragma section directive. __section_begin演算子のタイプは、voidへのポインタです。この組み込み演算子を使用するには、言語拡張を有効にしておく必要があります。
これらの演算子は、専用の名前を持つシンボルとして実装され、以下の名前でリンカマップファイルに表示されます。
演算子 | シンボル |
|---|---|
|
|
|
|
|
|
注記
これらの演算子を使用しない場合、リンカは同じ名前を持つセクションを連続して配置するとは限りません。これらの演算子(または同等のシンボル)を使用すると、セクションが指定のブロック内にあるかのようにリンカが動作します。これは、演算子または意味のある値が割り当てられるように、セクションが連続して配置されるためです。このことで、リンカ設定ファイルで指定したセクションの配置と矛盾が生じる場合、リンカでエラーが出力されます。
例
以下の例では、__section_begin演算子の型はvoid *です。
#pragma section="MYSECTION" ... section_start_address = __section_begin("MYSECTION");
標準Cに対する緩和
このセクションでは、一部のC規格の問題の一覧と、緩和について説明するとともに、小規模な構文の拡張についても解説します。
配列では、不完全な
struct型、union型、enum型を要素の型として使用できます。型は、配列が使用される場合はその前に、使用されない場合はコンパイル単位の終了までに完全にする必要があります。構造体の最後のメンバーとしてゼロ長配列は、ISO C99フレキシブル配列メンバとして同様の動作をします。これはGNU C コンパイラで実装されている拡張です。
フレキシブル配列メンバを持つ構造体は、別の構造体のメンバまたは配列要素として表示されます。これはGNU C コンパイラで実装されている拡張です。
拡張を使用して、
enumの名前を先に宣言しておき、後で中括弧で囲んだリストを指定することでその名前を解決できます。structやunion指定子末尾にセミコロンがなくても受け入れます。structやunion指定子の末尾にセミコロンがないと、ワーニング(エラーの代わりとして)が出力されます。NULLと
voidポインタの処理において、
voidへのポインタは必要に応じて別の型に暗黙的に変換されます。また、NULLポインタ定数は、必要に応じて適切な型のNULLポインタに暗黙的に変換されます。 標準C規格では、一部の演算子でこの動作が認められていますが、そうでないものもあります。イニシャライザでは、ポインタ定数値を整数型にキャストできます(整数型のサイズが十分に大きい場合)。ポインタのキャストに関する詳細については、キャストを参照してください。
レジスタ変数のアドレスの取得
C規格では、レジスタ変数として指定した変数のアドレスを取得することは不正です。コンパイラではこれは可能ですが、ワーニングが出力されます。
long floatのdoubleとしての取扱い整数リテラルの桁区切り文字(
1'000'000)がサポートされます。同一スコープ内で
typedefを繰り返し宣言することは可能ですが、ワーニングが出力されます。交換可能だが同一ではない型へのポインタ間(
unsigned char *、およびchar *)で代入、差分計算を行うことが可能です。これには、同一サイズの整数型へのポインタが含まれます。ワーニングが出力されます。文字列リテラルを任意の種類の文字へのポインタに代入することは可能であり、ワーニングは出力されません。
左辺値でない配列式は、使用時に配列の最初の要素へのポインタに変換されます。この拡張は、プリプロセッサディレクティブの後にテキストを配置できるようにするもので、厳密なC規格モードを使用していない場合に有効になります。この言語拡張の目的は、レガシーコードのコンパイルをサポートすることであり、このフォーマットで新しいコードを記述することは推奨しません。
enumリスト最後の余分なカンマenumリストの最後に、余分なカンマを付けてもかまいません。厳密なC規格モードでは、ワーニングが出力されます。}の前のラベルC規格では、ラベルに続けて少なくとも1つの文を記述する必要があります。したがって、ラベルをブロックの最後に配置するのは不正になります。 コンパイラはこれを許可しますが、ワーニングが出力されます。これは、
switch文のラベルについても同様です。空白の宣言(セミコロンのみ)は可能ですが、リマークが出力されます(リマークが有効な場合)。
C規格では、静的な配列、struct、unionのイニシャライザ式は、すべて中括弧で囲む必要があります。
単一の値のイニシャライザは、中括弧なしで記述できますが、ワーニングが出力されます。コンパイラは次の式を受け入れます。
struct str { int a; } x = 10;他のスコープでの宣言
他のスコープでの外部/静的宣言は可視になります。以下の例では、変数
yはif文の本体でのみ可視になるべきですが、関数の最後でも使用でき、 ワーニングが出力されます。int test(int x) { if (x) { extern int y; y = 1; } return y; }関数およびブロックスコープ内の静的関数
静的関数を関数およびブロックスコープ内で宣言可能。宣言はファイルスコープに移動します。
数値の構文に従って数値の走査が行われる
数値は、
pp-number構文ではなく、数値の構文に従って走査されます。このため、0x123e+1は1つの有効なトークンではなく、3つのトークンとして走査されます。(--strictオプションを使用する場合、代わりにpp-number構文が使用されます)。翻訳単位(入力ファイル)は宣言が空になっていることが可能です。
ポインタ型の割り当ては、代入先の型に、トップレベルでない型修飾子が追加されている場合には可能です(
int **からconst int **への代入など)。比較およびポインタが異なるようなペアのポインタ型も可能です。ワーニングが出力されます。異なる関数型のポインタは明示的な型キャストなしで等式(
==)または不等式(!=)へ代入されたり、比較されたりすることが可能です。ワーニングが出力されます。この拡張はC++モードでは使用できません。アセンブラ文が許可されます。これは厳密なCモードでは無効です。それは、暗示的に宣言された
asm関数の呼び出すためのC標準と矛盾するためです。非標準のプリプロセスする
#include_nextディレクティブがサポートされます。これは#includeディレクティブのバリアントです。現在のソースファイル(#include_nextディレクティブが含まれているもの)があるディレクトリに続く検索パス上のディレクトリ内でのみ、指定されたファイルを検索します。これはGNU C コンパイラで実装されている拡張です。非標準のプリプロセスする
#warningディレクティブがサポートされます。それは#errorディレクティブとよく似ていますが、処理するときに、壊滅的なエラーではなく警告を発します。このディレクティブは厳密モードでは認識されません。これはGNU C コンパイラで実装されている拡張です。混合した文字連結が許可されています。
wchar_t * str="a" L "b";
GNUスタイルのケース範囲が許可されます。(
case 1 ... 5:)....の前後に余分なスペース文字があることに注意してください。GNUスタイルで指定されたイニシャライザの範囲が許可されます。
...の前後に余分なスペース文字があることに注意してください。例:
int widths[] = {[0 ... 9] = 1, [10 ... 99] = 2, [100] = 3};IAR拡張機能が有効になっている場合、式タイプへの参照を示すために、非標準の演算子
typeofがサポートされます。構文はsizeofと同じですが、セマンティクスはtypedefで定義された型名に似ています。これはGNU C コンパイラで実装されている拡張です。非標準キーワード
__auto_typeは、IAR拡張が有効なときにサポートされます。__auto_typeキーワードを使用して変数を宣言すると、そのタイプが、自動的にそのイニシャライザを基にした派生となります。__auto_typeは、C++11のautoキーワードと同様ですが、使用できるタイミングがより制限されています。これはGNU C コンパイラで実装されている拡張です。