Lite-C for C/C++ programmers

Zorro's lite-C compiler uses the familiar syntax of C based languages such as C, C++, C#, or Javascript. Although it has some differences to allow a simpler compiler structure and faster compiling, it is 'compatible enough' to access the Windows API and even use complex external C++ libraries such as DirectX or OpenGL. Therefore it can be used to write any normal computer program (see Mandelbrot).

The differences of lite-C to standard C/C++ are listed here:

No early if(A && B) abort

The && and || operators are aliased with and and or, but can of course still be used. In C/C++, comparisons are early aborted when a && is encountered and the expression so far evaluated to false, or when a || is encountered and the expression evaluated to true. Lite-C always calculates the expressions up to the end; the order of comparisons plays no role. This requires a different syntax for checking the value of a struct pointer and its element in the same expression:
if((ptr != NULL) && (ptr->element == ..)) .. // C/C++
if(ptr != NULL) if(ptr->element == ..) .. // lite-C 

Trinary operators

Lite-C does not support the comparison ? expression : expression; syntax. Use the ifelse statement instead.
x = (x<0 ? -1 : 1); // C/C++
x = ifelse(x<0,-1,1);  // lite-C 

Multiple operations in one command

Lite-C does not support the comma for clustering multiple operations in one command.
x = 2, y = 2; // C/C++
x = y = 2; // lite-C x = 2; y = 2; // lite-C

Struct and array initialization

In C/C++ structs can be initialized just like arrays, by giving a list of member values. This is only supported for numerical arrays in lite-C. Lite-C initializes all other arrays and structs automatically to zero.

Struct copying

In C++, structs can be copied into each other with the '=' operator. In C or lite-C, use memcpy for copying structs or arrays:
// C++:
D3DXVector3 vecA, vecB;
...
vecA = vecB;

// lite-C:
D3DXVector3 vecA, vecB;
...
memcpy(&vecA,&vecB,sizeof(D3DXVector3));

Enums

Enums are not supported and must be replaced by defines:
enum RGB { RED=1; BLUE=2; GREEN=3 }; // C/C++

#define RED 1 // lite-C #define BLUE 2 #define GREEN 3

Unions

Union members of the same type can be substituted by a #define, and union members of different type can be treated as a different members of the struct. Example:
typedef struct S_UNION { 
   int data1;
   union { int data2; float data3; };
   union { int data4; int data5; };
} S_UNION; // C/C++

typedef struct S_UNION { int data1; int data2; float data3; int data4; } S_UNION; // lite-C #define data5 data4

If the struct size must not change, or if for some reason the program requires different variable types to occupy the same place in the struct, a special conversion function can be used to convert the type of a variable without converting the content:

typedef struct S_UNION { 
   int data1;
   union { int data2; float data3; };

} S_UNION; // C/C++
...
S_UNION s_union;
s_union.data3 = 3.14;

typedef struct S_UNION { int data1; int data2; } S_UNION; // lite-C #define data3 data2 ... int union_int_float(float x) { return *((int*)&x); } ... S_UNION s_union; s_union.data3 = union_int_float(3.14);

Function pointers

In C/C++, function pointers are declared like this: int (*foo)(int a, int b);. In lite-C there's no difference between function prototypes and function pointers: int foo(int a, int b);. See details under pointers.

Signed, unsigned, extern, const, register...

In lite-C, variables are only defined by their type; further qualifiers are not used. Float, double, var, long, int are generally signed, and pointers, char and short are generally unsigned, according to the normal way they are used. The include\litec.h file contains definitions for all usual unsigned variables like DWORD or WORD that are used in Windows functions. So using unsigned variables normally does not cause any problems. However you need to take care when variables exceed their range. For instance, subtracting 1 from (DWORD)0 results in -1 under lite-C, but in 0xFFFFFFFF in standard C/C++.

Relaxed variable and function type checking

Lite-C allows a lot of things where a C++ compiler would issue a warning, such as assigning an int to a pointer, or not returning a value from a function. This relaxed checking is heavily used in the predefined scripts for making the code shorter and less complicated, but it also allows the user to make more mistakes.

main() and run() functions

The main() function works like in C. The run() function indicates that the program is a strategy script. It is called once before the start of the strategy for initialization, and then once for each bar.

Using C library or Windows API functions

Lite-C already contains the most often used functions from the standard C/C++ libraries - they are listed in <litec.h>, which is automatically included in all scripts without explicit #include statement. So you normally won't need to include C headers such as stdio.h or math.h. If you need a function that is not contained in <litec.h>, add it as described under Using the Windows API. Here's a brief instruction of how to add an external function to lite-C:

If you need certain structs or variable types that are not yet contained in include\windows.h or in the other standard include files, just add them from their original file either into your script. If you think that a certain function, struct, or variable type is often needed, suggest its inclusion on the Zorro future forum.

See also:

Pointers, Structs, Functions, API

► latest version online