LabWindows/CVI 9.0 introduces support for a number of useful additions to the C language as specified in ISO/IEC 9899:1999 standard. LabWindows/CVI is not a fully conforming C99 compiler, but rather supports some C99 features as extensions to the ANSI C language.
LabWindows/CVI supports the following C99 extensions:
Because older versions of LabWindows/CVI and most other commercially available C compilers do not support C99, code that uses these features may have portability issues. LabWindows/CVI allows you to disable C99 extension support on a per-project or per-file basis for when portability is a concern. When you create a new project in LabWindows/CVI 9.0 or later, C99 extensions are enabled by default. Existing projects must have this option explicitly enabled. Enable and disable C99 extensions using the Build with C99 extensions option in the Build Options dialog box.
Image: Build with C99 extensions option on the Build Options dialog.
You can override this project-wide setting on a per-file basis by using the following pragmas in t source code:
The pragmas affect the compilation of all code that follows in that module. Use the C99_extensions_off pragma to disable C99 extensions and enforce the portability of a particular file.
Whereas ANSI C89 requires all variables be declared at the top of a function or local block, C99 allows a declaration to appear anywhere within the block. The scope of local variables extend from their declaration to the end of the block in which they are defined.
foo();
int bar;
foo();
You also can declare variables in the initialization section of a for loop. The scope of local variables defined in the for loop extend from their declaration to the end of the for loop in which they are defined.
for (int i = 0; i < 10; ++i)
printf("%d", i);
Whereas ANSI C requires local array declarations to have constant size expressions, C99 allows arbitrary size expressions:
void foo (int n)
{
int bar[n+1];
...
}
For an array with a non-constant size expression, the number of elements is evaluated and stack storage is allocated at run time, when the declaration comes into scope. Like any other local variable, the storage is automatically deallocated when the object goes out of scope. For small to moderately large, temporary allocations, you can use variable-length arrays as an alternative to malloc. This helps avoid memory leaks by moving the deallocation burden from the programmer to the compiler. By default, LabWindows/CVI programs reserve a stack of 250,000 bytes (roughly 30,000 doubles), so an allocation on that scale is inappropriate as a variable-length array declaration since it may cause a stack overflow. The heap can tolerate much larger allocations.
There are some behavioral considerations and restrictions for variable-length arrays that are a direct result of their run-time allocation. Because the size can only be known at run time, you cannot declare global or static variable-length arrays. Declarations of variable-length arrays cannot have initializers. If you use the sizeof operator with a variable-length array, the operator evaluates only at run time when the length of the array is known. If the size expression of a variable-length array evaluates to a non-positive number at run time, the program generates a fatal run-time error. You can use a goto statement to jump within the scope of a variable-length array, but you cannot jump past a declaration of an object of variably modified type.
ANSI C requires that an initializer list for an array, struct, or union, begin with the first member of the aggregate, and proceed on in sequential order, without skipping any members. C99 provides a special “designator” syntax that allows the initialization of specific array, struct, or union members.
For structs or unions, to initialize a member x, use the designator .x= followed by the initial value:
struct S1
{
int a;
float b;
char c[3];
} foo = { .b=0.5, .a=1, .c="hi" };
To initialize an array member at index i, use the designator [i]= followed by the initial value:
float bar[100][100] = { [99][99] = 1.0, [1][1] = 1.0 };
Initialize members in any order you wish, and avoid explicitly initializing members you do not care about. Any members not explicitly initialized are implicitly initialized with 0. To this end, designated initializers are handy for static initialization of sparse arrays or matrices.
Designators may be composed to initialize members of more complex data structures:
struct S2
{
double d[2];
} baz[2] = { [1].d[0]=0.5, [0].d[1]=0.6 };
results in: { { { 0.0, 0.6 } }, { { 0.5, 0.0 } } }
Designated initializers may be interspersed within standard initialization lists. Any non-designated initializer initializes the next sequential member in the aggregate:
struct S1
{
int a;
float b;
char c[3];
} foo = { .c=’h’, ‘i' /* foo.c[1] */, .a=1, 2.1 /* foo.b */ };
In C99, macro declarations can accept a variable number of arguments when the last member of the argument declaration list is an ellipsis (...). Use a variable argument list if the number and type of arguments in the function might vary:
#define debug_printf (format, ...) fprintf (stderr, format, __VA_ARGS__);
To access the arguments in the list, you must specify at least one fixed argument. Use the __VA_ARGS__ macro to access the variable argument list. You also can use the va_list, va_start, va_arg, and va_end macros in the stdarg.h file located in the cvi\include\ansi directory to work with variable argument lists.
You can initialize the elements of an aggregate (array, struct, or union) using an expression instead of a constant only:
foo (float a, float b)
{
float freqs[2] = { a-b, a+b };
}
You can use the __func__ predefined identifier to access the name of the function in which it is used. This identifier behaves as a static string variable.
void foo (void)
{
printf ("In function %s\n", __func__); /* prints "In function foo." */
}
LabWindows/CVI recognizes the restrict and inline keywords from the C99 specification.
The restrict pointer type qualifier has no effect on the code generated by the compiler, but syntactically correct usage of the keyword is accepted and produces no compile errors.
LabWindows/CVI does not support code inlining. However, syntactically correct usage of the inline function specifier is accepted and results in semantically correct behavior. If all declarations of a function within a module specify the inline keyword and do not specify the extern keyword, LabWindows/CVI handles the definition of the function as a static definition.
The mark LabWindows is used under a license from Microsoft Corporation. Windows is a registered trademark of Microsoft Corporation in the United States and other countries.