このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
C/C++ コード生成のための変数定義のベスト プラクティス
MATLAB Function ブロックからコードを生成する場合、ブロック内の MATLAB® コードが C/C++ コード生成の要件に準拠していることを確認する必要があります。MATLAB コードで機能するコーディング方法がコード生成では機能しないことがあります。コードを最適化し、シミュレーション エラーを回避するには、以下のベスト プラクティスに従います。
変数を使用する前に明示的に定義する
C/C++ コード生成をするためには、変数の値とプロパティを明示的に定義してからそれを演算に使用したり出力として返したりする必要があります。これを行うと、変数を定義しなかった場合に発生するエラーを防ぐことができます。
メモ
変数を定義する場合、既定ではローカルとなり、関数呼び出し間で存続されません。変数を永続させるには、関数 persistent
を使用します。
すべての実行パスにおける変数の定義
if
ステートメントで決まる実行パスなど、すべての実行パスで変数を定義する必要があります。変数を関数への入力として使用する前に定義する以下の MATLAB コードについて考えます。
... if c <= 0 x = 11; end % Later in your code ... if c > 0 % Use x in the function foo foo(x); end ...
c <= 0
の場合にのみ値に x
を代入し、c > 0
の場合にのみ x
を使用します。c
の値に応じて、このコードは MATLAB ではエラーなく機能できます。ただし、この MATLAB コードから C/C++ コードを生成しようとすると、コード生成が失敗します。これは、c > 0
のときの実行パス上で x
が未定義であるとコード ジェネレーターによって検出されるためです。このコードをコード生成に適したものにするには、x
を使用する前に次のように定義します。
x = 0; ... if c <= 0 x = 11; end % Later in your code ... if c > 0 % Use x in the function foo foo(x); end ...
すべての構造体フィールドの定義
すべての実行パスの各構造体フィールドも定義する必要があります。以下の MATLAB コードについて考えます。
... if c > 0 s.a = 11; disp(s); else s.a = 12; s.b = 12; end % Use s in the function foo foo(s); ...
if
ステートメントの最初の部分はフィールド a
しか使用せず、else
ステートメントはフィールド a
と b
を使用しています。このコードは MATLAB では機能しますが、C/C++ コード生成時にはコンパイル エラーになります。このエラーを回避するには、構造体を使用した後にその構造体にフィールドを追加しないでください。詳細については、コード生成のための構造体の定義を参照してください。このコードを C/C++ コード生成に適したものにするには、s
のフィールドを使用する前に以下のように定義します。
... % Define fields in structure s s = struct("a", 0, "b", 0); if c > 0 s.a = 11; disp(s); else s.a = 12; s.b = 12; end % Use s in the function foo foo(s); ...
変数プロパティを代入し直す際の注意事項
特定の変数には、最初の代入のときとは異なるクラス、サイズ、実数/複素数の値を代入し直すことができます。変数プロパティの再代入を参照してください。ただし、変数に対して最初の代入の後に型を再割り当てすると、多くの場合、コード生成時にコンパイル エラーが返されます。一般に、各変数には特定のクラス、サイズ、型および実数/複素数を割り当てます。
変数の数値データ型を定義する
MATLAB では、double
が既定の数値データ型です。その他のデータ型の変数を定義するには、定義時に正しい接頭辞または演算子を使用してデータ型を明示的に定義する必要があります。使用するデータ型に留意してください。コードで異なるデータ型に代入された変数を使用すると、型の不一致エラーが発生する可能性があります。
たとえば、以下のコードは変数 x
を double として定義し、y
を 8 ビット整数として定義します。
x = 15; y = uint8(x);
MATLAB でサポートされる型の詳細については、数値型を参照してください。
インデックス付けされた変数を代入する前に行列を定義する
現在のサイズを超える要素の書き込みを行って変数を拡大させると、end+1 インデックスを使用するか他の方法で変数を可変サイズとして先に定義しない限り、コンパイル時エラーまたはランタイム エラーが発生します。end + 1 のインデックス付けを使用して配列と cell 配列を拡張するためのコード生成 (MATLAB Coder)およびコード生成のための可変サイズ データの定義を参照してください。[シンボル] ペインとプロパティ インスペクターで出力変数を可変サイズとして指定することもできます。可変サイズの MATLAB Function ブロック変数の宣言を参照してください。end+1 インデックスを使用することも配列を可変サイズとして定義することもなくサイズ関連のエラーが生じないようにするには、配列の要素に値を代入する前に配列の最大サイズを定義します。
たとえば、次の代入はコード生成時にエラーになります。
g = zeros(3,3); g(5,2) = 14.6;
このコードを修正するには、十分なサイズの行列 g
を定義します。
g = zeros(5,5); g(5,2) = 14.6;
行列のインデックス付けの詳細は、コード生成における行列のインデックス操作に関する MATLAB との非互換性を参照してください。
固定サイズのベクトルを使用した配列のインデックス付けの試行
コード生成では可変サイズの配列がサポートされていますが、可変サイズの配列には追加のメモリが必要になるため、パフォーマンスが低下する可能性があります。可能な場合は、配列のインデックス付けには定数値のベクトルを使用します。以下に例を示します。
... % extract 7 elements from A using a constant-value vector B = A(1:7); ...
B
が固定サイズであると認識します。colon
演算子と変数値を使用して配列にインデックスを付けた場合、コード ジェネレーターは配列が固定サイズなのか可変サイズなのかを常に正しく判別できるわけではありません。たとえば、次の配列はいずれも、i
の値に関係なく固定サイズです。
... % extract 7 elements from A using a fixed-size vector B = A(i-1:i+5); C = A(-1+2*i:5+2*i); ...
i
の値がわかっている場合、コード ジェネレーターは B
と C
の両方が固定サイズの配列であると認識します。ただし、コード生成時に i
の値がわからない場合、コード ジェネレーターは B
を固定サイズと認識しますが、C
を可変サイズとして定義します。そのため、サイズが変わらない固定サイズの配列を定義しようとした場合でも、コード ジェネレーターではその配列が可変サイズとして解釈および指定されることがあります。 そのような場合に、MATLAB コードを書き換え、定義されている配列のサイズが変わらないことをコード ジェネレーターに強制的に認識させることが可能な場合があります。たとえば、上記の C
の定義を書き換え、コード生成時に不明な変数 (i
) に関係している数学操作から配列インデックス式を抽出できます。
... % extract 7 elements from A using a fixed-size vector C = A(2*i+(-1:5)); ...
C
を固定サイズの配列として認識します。 他のコード パターンでは、配列インデックスに配列サイズに影響する変数が含まれているが、そうした変数がコンパイル時に既知であることがあります。そうした状況では、抽出された配列は実際には固定サイズですが、コード ジェネレーターがその配列を固定サイズと識別できず、可変サイズとして扱うことがあります。場合によっては、固定サイズの配列を生成するようにそのようなコードを書き換えることもできます。この例では、配列 D_varSize
と D_fixSize
は同一です。しかし、コード ジェネレーターは D_varSize
を可変サイズとして、D_fixSize
を固定サイズとして定義します。
... width = 25; D_varSize = A(i-width:i+width); % D_varSize is variable-size if i is unknown at compile time D_fixSize = A(i+(-width:width)); % D_fixSize is fixed-size whether or not i is unknown at compile time ...
参考
coder.nullcopy
| persistent
| coder.extrinsic