TCC compiles so fast that even for big projects Makefiles may not be necessary.
TCC not only supports ANSI C, but also most of the new ISO C99 standard and many GNUC extensions.
TCC can also be used to make C scripts, i.e. pieces of C source that you run as a Perl or Python script. Compilation is so fast that your script will be as fast as if it was an executable.
TCC can also automatically generate memory and bound checks while allowing all C pointers operations. TCC can do these checks even if non patched libraries are used.
#define dprintf(level, __VA_ARGS__) printf(__VA_ARGS__)dprintf can then be used with a variable number of parameters.
struct { int x, y; } st[10] = { [0].x = 1, [0].y = 2 }; int tab[10] = { 1, 2, [5] = 5, [9] = 9};
int *p = (int []){ 1, 2, 3 };to initialize a pointer pointing to an initialized array. The same works for structures and strings.
double d = 0x1234p10;is the same as writing
double d = 4771840.0;
int a[10] = { [0] 1, [5] 2, 3, 4 };
struct { int x, y; } st = { x: 1, y: 1};instead of
struct { int x, y; } st = { .x = 1, .y = 1};
switch(a) { case 1 ... 9: printf("range 1 to 9\n"); break; default: printf("unexpected\n"); break; }
int a __attribute__ ((aligned(8), section(".mysection")));
int my_add(int a, int b) __attribute__ ((section(".mycodesection"))) { return a + b; }
Note that pointer size is unchanged and that code generated with bound checks is fully compatible with unchecked code. When a pointer comes from unchecked code, it is assumed to be valid. Even very obscure C code with casts should work correctly.
To have more information about the ideas behind this method, check here.
Here are some examples of catched errors:
{ char tab[10]; memset(tab, 0, 11); } | Invalid range with standard string function |
{ int tab[10]; for(i=0;i<11;i++) { sum += tab[i]; } } | Bound error in global or local arrays |
{ int *tab; tab = malloc(20 * sizeof(int)); for(i=0;i<21;i++) { sum += tab4[i]; } free(tab); } | Bound error in allocated data |
{ int *tab; tab = malloc(20 * sizeof(int)); free(tab); for(i=0;i<20;i++) { sum += tab4[i]; } } | Access to a freed region |
{ int *tab; tab = malloc(20 * sizeof(int)); free(tab); free(tab); } | Freeing an already freed region |
usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b] [-i infile] infile [infile_args...]
'-Idir' | Specify an additionnal include path. The default ones are: /usr/include, /usr/lib/tcc, /usr/local/lib/tcc. |
'-Dsym[=val]' | Define preprocessor symbol 'sym' to val. If val is not present, its value is '1'. Function-like macros can also be defined: '-DF(a)=a+1' |
'-Usym' | Undefine preprocessor symbol 'sym'. |
'-lxxx' | Dynamically link your program with library libxxx.so. Standard library paths are checked, including those specified with LD_LIBRARY_PATH. |
'-g' | Generate run time debug information so that you get clear run time error messages: test.c:68: in function 'test5()': dereferencing invalid pointer instead of the laconic Segmentation fault. |
'-b' | Generate additionnal support code to check memory allocations and array/pointer bounds. '-g' is implied. Note that the generated code is slower and bigger in this case. |
'-i file' | Compile C source 'file' before main C source. With this command, multiple C files can be compiled and linked together. |