Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

C/C++ コード生成のための変数定義のベスト プラクティス

変数を使用する前に代入によって定義する

C/C++ コード生成をするためには、明示的かつ明確に変数のクラス、サイズ、実数/複素数を定義してからそれを演算に使用したり出力としてことをお勧めします。変数は代入によって定義しますが、代入をするとその値のみでなく、値が表すサイズ、クラス、実数/複素数も新しい変数にコピーされることに注意してください。例:

代入: 定義:
a = 14.7;a は実数で double のスカラー値。
b = a;ba (実数で double のスカラー値) のプロパティをもつ。
c = zeros(5,2);c は実数の double の 5 行 2 列の配列。
d = [1 2 3 4 5; 6 7 8 9 0];d は実数の double の 5 行 2 列の配列。
y = int16(3);y は実数で 16 ビットの整数スカラー値。

このようにしてプロパティを定義し、C/C++ コード生成中に変数が必要な実行パス上で定義されるようにします。

変数に代入するデータには、スカラー、行列、構造体があります。変数が構造体の場合は、個別のフィールドのプロパティを明示的に定義してください。

新しい変数を、代入したデータの値に初期化すると、生成されたコード内に余分なコピーが発生する場合があります。余分なコピーを回避するために、生成されたコード内の変数の余分なコピーを排除するで説明されているように coder.nullcopy コンストラクトを使用して値を初期化せずに変数を定義することができます。

変数を定義する場合、既定ではローカルとなり、関数呼び出し間で存続されません。変数を永続させる方法については、persistent を参照してください。

例1 複数の実行パスでの変数の定義

以下の MATLAB® コードについて考えます。

...
if c > 0
  x = 11;
end
% Later in your code ...
if c > 0
  use(x);
end
...
ここで、x は、c > 0 の場合にのみ代入され、c > 0 の場合にのみ使用されます。このコードは MATLAB では機能しますが、コード生成時にはコンパイル エラーになります。それは、x が一部の実行パス (c <= 0 のとき) 上で未定義であると検出されるためです。

このコードをコード生成に適したものにするには、x を使用する前に次のように定義します。

x = 0;
...
if c > 0
  x = 11;
end
% Later in your code ...
if c > 0
  use(x);
end
...

例2 構造体のフィールドの定義

以下の MATLAB コードについて考えます。

...
if c > 0 
  s.a = 11;
  disp(s);
else
  s.a = 12;
  s.b = 12;
end
% Try to use s
use(s);
...
ここで、if ステートメントの最初の部分はフィールド a しか使用せず、else 節はフィールド a と b を使用しています。このコードは MATLAB では機能しますが、C/C++ コード生成時には構造体の型の不一致が検出されてコンパイル エラーになります。このエラーを回避するには、構造体に特定の操作を行った後にその構造体にフィールドを追加しないでください。詳細は、コード生成のための構造体の定義を参照してください。

このコードを C/C++ コード生成に適したものにするには、s を使用する前にすべてのフィールドを定義します。

...
% Define all 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
use(s);
...

変数を代入し直す際の注意事項

一般に、C/C++コード生成では "1 変数/ 1 タイプ" というルールに従うことをお勧めします。つまり、それぞれの変数が 1 つの特定のクラス、サイズ、実数/複素数をもっていなければなりません。一般に、変数に対して最初の代入の後にプロパティを再割り当てすると、コード生成時にコンパイル エラーが発生します。ただし、これには変数プロパティの再代入に示されるような例外があります。

変数定義で型キャスト演算子を使用する

既定では、定数は double 型です。別の型の変数を定義するには、変数定義で型キャスト演算子を使用できます。たとえば、以下のコードは変数 y を整数として定義します。

...
x = 15; % x is of type double by default.
y = uint8(x); % y has the value of x, but cast to uint8.
...

インデックス付けされた変数を代入する前に行列を定義する

MATLAB から C/C++コードを生成する際、要素に対して現在のサイズを超える書き込みを行って変数を拡大させることができません。そのようなインデックス操作を行うとランタイム エラーが発生します。要素に値を代入する前に行列を定義しなければなりません。

たとえば、コード生成では以下のような最初の代入はできません。

g(3,2) = 14.6; % Not allowed for creating g
               % OK for assigning value once created

行列のインデックス付けの詳細は、コード生成における行列のインデックス操作に関する MATLAB との非互換性を参照してください。

配列のインデックス付けには定数値のベクトルを使用する

配列のインデックス付けには、一定でないオブジェクトを含む範囲は使用せずに、定数値のベクトルを使用することをお勧めします。

場合によっては、colon演算子を含む式について、固定サイズであるか可変サイズであるかをコード ジェネレーターで判別できないことがあります。配列のインデックス付けに定数値のベクトルを使用すると、生成コードで不必要に可変サイズの配列として作成されるのを防ぐことができます。

たとえば、配列 out が乱数行ベクトル A でインデックス付けされた変数 i を使用して作成されているとします。

...
% extract elements i through i+5 for processing
A = rand(1,10);
out = A(i:i+5); % If i is unknown at compile time, out is variable-size
...

i がコンパイル時に定数値になる場合、コード ジェネレーターは out に対して固定サイズのオブジェクトを生成します。i がコンパイル時に不明な場合は、コード ジェネレーターは out に対して生成コードで可変サイズの配列を生成します。

コード ジェネレーターで可変サイズの配列が作成されないようにするには、前のコード スニペットを次のパターンで書き換えます。

...
% extract elements i through i+5 for processing
A = rand(1,10);
out = A (i+(0:5)); % out is fixed-size, even if i is unknown at compile time
...

このパターンにすると、コンパイル時に不明な反復値をもつ固定サイズの配列を生成できます。推奨されるもう 1 つの書き換え例は次のとおりです。

width = 25;              
A = A(j-width:j+width);  % A is variable-size, if j is unknown at compile time 
fsA = A(j+(-width:width)); % This makes A fixed-size, even if j is unknown at compile time
...

参考

|

関連するトピック