Best Practices for Defining Variables for C/C++ Code Generation
Define Variables By Assignment Before Using Them
For C/C++ code generation, you should explicitly and unambiguously define the class, size, and complexity of variables before using them in operations or returning them as outputs. Define variables by assignment, but note that the assignment copies not only the value, but also the size, class, and complexity represented by that value to the new variable. For example:
Assignment: | Defines: |
---|---|
a = 14.7; | a as a real double scalar. |
b = a; | b with properties of a (real
double scalar). |
c = zeros(5,2); | c as a real 5-by-2 array of doubles. |
d = [1 2 3 4 5; 6 7 8 9 0]; | d as a real 5-by-2 array of doubles. |
y = int16(3); | y as a real 16-bit integer scalar. |
Define properties this way so that the variable is defined on the required execution paths during C/C++ code generation.
The data that you assign to a variable can be a scalar, matrix, or structure. If your variable is a structure, define the properties of each field explicitly.
Initializing the new variable to the value of the assigned data
sometimes results in redundant copies in the generated code. To avoid
redundant copies, you can define variables without initializing their
values by using the coder.nullcopy
construct as
described in Eliminate Redundant Copies of Variables in Generated Code.
When you define variables, they are local by default; they do
not persist between function calls. To make variables persistent,
see persistent
.
Consider the following MATLAB® code:
... if c > 0 x = 11; end % Later in your code ... if c > 0 use(x); end ...
c >
0
and used only when c > 0
. This
code works in MATLAB, but generates a compilation error during code generation because it
detects that x is undefined on some execution paths (when c
<= 0
).To make this code suitable for code generation, define x before using it:
x = 0; ... if c > 0 x = 11; end % Later in your code ... if c > 0 use(x); end ...
Consider the following MATLAB code:
... if c > 0 s.a = 11; disp(s); else s.a = 12; s.b = 12; end % Try to use s use(s); ...
if
statement uses only the
field a, and the else
clause
uses fields a and b. This code
works in MATLAB, but generates a compilation error during C/C++
code generation because it detects a structure type mismatch. To prevent
this error, do not add fields to a structure after you perform certain
operations on the structure. For more information, see Structure Definition for Code Generation.To make this code suitable for C/C++ code generation, define all fields of s before using it.
... % 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); ...
Use Caution When Reassigning Variables
In general, you should adhere to the "one variable/one type" rule for C/C++ code generation; that is, each variable must have a specific class, size and complexity. Generally, if you reassign variable properties after the initial assignment, you get a compilation error during code generation, but there are exceptions, as described in Reassignment of Variable Properties.
Use Type Cast Operators in Variable Definitions
By default, constants are of type double
.
To define variables of other types, you can use type cast operators
in variable definitions. For example, the following code defines variable y
as
an integer:
... x = 15; % x is of type double by default. y = uint8(x); % y has the value of x, but cast to uint8. ...
Define Matrices Before Assigning Indexed Variables
When generating C/C++ code from MATLAB, you cannot grow a variable by writing into an element beyond its current size. Such indexing operations produce run-time errors. You must define the matrix first before assigning values to its elements.
For example, the following initial assignment is not allowed for code generation:
g(3,2) = 14.6; % Not allowed for creating g % OK for assigning value once created
For more information about indexing matrices, see Incompatibility with MATLAB in Matrix Indexing Operations for Code Generation.
Index Arrays by Using Constant Value Vectors
It is a best practice to use constant value vectors to index arrays instead of using ranges that contain nonconstant objects.
In some cases, the code generator is unable to determine whether an expression
containing the colon
operator is fixed-size or variable-size. Use constant
value vectors to index arrays to prevent them from being unnecessarily created as
variable-size arrays in the generated code.
For example, the array out
has been created by using the variable
i
indexed through the random row vector A
.
... % 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 ...
If i
is a compile-time constant value, the code generator produces
a fixed-size object for out
. If i
is unknown at
compile time, the code generator produces a variable-size array for out
in the generated code.
To prevent the code generator from creating variable-size arrays, the previous code snippet is rewritten in this pattern:
... % 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 ...
This pattern enables you to generate fixed-size arrays that have iterator values unknown at compile-time. Another example of the recommended rewrite is:
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 ...