General

Omitting the int keyword

Declarations in the global scope and in function parameters implicitly default to an int type, meaning the keyword may be dropped in these cases.

Instead of:

int a,b[5],c;
int main(int argc){...}

Use:

a,b[5],c;
main(argc){...}

TCC normally doesn't allow pointer declarations without specifying a type.

*p; // error: declaration expected

But TCC accepts pointer declarations as subsequent elements in a list:

a,*p;
// works like
int*p,a;

BSS section

Variables and arrays declared in the global scope of a program (that is, outside of a function) are initialized to 0.

Instead of:

a=0,b=0,c=0;main(){...}

Use:

a,b,c;main(){...}

K&R-style syntax for function parameters

In certain cases, it may be shorter to specify function parameter types separately. Instead of:

int func(int a, int b, char c, char *d, int e) { ... }

Use:

int func(a, b, c, d, e) char c, *d; { ... }

Variable starting with 1

In many cases, it is useful to have a variable that starts with the value 1. In holes that have no arguments, argc is a perfect fit for this.

Instead of:

a=1;main(){...}

Use:

main(a){...}

Writing character constants as integers

char values may be implicitly converted to and from numeric types, with the character's ASCII value representing its numeric value. This can save a single byte on character constants with an ASCII value below 100.

Instead of:

char a = 'a', b = 'b', c = 'c';

Use:

char a = 97, b = 98, c = 99;

Newlines in strings

The C compiler used on code.golf, tcc, allows newlines in strings.

Instead of:

printf("%d\n",n);

Use:

printf("%d
",n);

Omitting the return keyword

Sometimes, you can omit the return keyword in a function and still have it return the correct value, so it's worth testing whether you can do so.

For example, consider this code:

add(a,b){a+b;}
main()
{
    printf("%d\n", add(4, 5));
}

Even though the return keyword has been omitted in the add function, this program still prints 9. The return in main can be avoided.

There is another option in some circumstances where this wouldn't normally work. In the following example removing the return b; causes it to always return -1, as n has been evaluated more recently than b.

pow(b,n){
	int b_copy=b;
	for(;n--;)b*=b_copy;
	return b;
}
main(){
	printf("%i", pow(3,3));
}

However the following will correctly return b:

pow(b,n){
	int b_copy=b;
	for(;n--;)b*=b_copy;
	b=b;
}
main(){
	printf("%i", pow(3,3));
}

Example: print all arguments

main(c,v)int**v;{for(;;)puts(*++v);}

print substrings with printf

You can print a substring with printf in at least two ways:

The example prints out "'test'" twice:

main()
{
    char data[]="This is a test value!";
    printf("'%.*s'", 4, &data[10]); //dynamic cut out
    puts("");
    printf("'%.4s'", &data[10]); //static cut out
}

Comparisons

Replace logical && by bitwise &

Replacing && by & does not work in every case, but it can save one character.

Instead of:

if(a&&b)

Use:

if(a&b)

Conditional/Ternary operator

Instead of:

if(a==3)puts("foo!");

Use:

a==3?puts("foo!"):0;

Even higher savings can be achieved, when the else-path is required.

Instead of:

if(a==3)
    puts("foo!");
else
    puts("bar!");

Use:

a==3?puts("foo!"):puts("bar!");

To improve the example even further: you can also move the conditional into a function call.

Instead of:

a==3?puts("foo!"):puts("bar!");

Use:

puts(a==3?"bar!":"foo!");

Commas vs. curly braces

Curly braces can often be omitted, by concatenating commands together by replacing semicolons with commas.

Instead of:

if(a==123)
{
    x=2;
    Foo();
}

Use:

if(a==123)x=2,Foo();

Create an infinite loop

Instead of:

while(1)

Use:

for(;;)

Wide character strings

String literals with an L prefix are wide character strings that can contain Unicode characters beyond ASCII. They create a zero-terminated, static wchar_t array holding code points up to 0x10ffff. wchar_t is typedef'd to int on most Unix platforms.

// Prints the numbers 50, 100, 500, 1000.
i;main(){for(;i<4;i++)printf("%d\n",L"2dǴϨ"[i]);}

A single wide character can also be used to store a two-character ASCII string using the little-endian memory representation of a 32-bit int. This is mainly useful when golfing for Unicode chars.

// Prints the strings "th", "st", "nd", "rd".
i;main(){for(;i<4;i++)printf("%s\n",L"桴瑳摮摲"+i);}

In rare occasions, a three-character string can be stored in a single wide character.

printf("%d\n",v); // ASCII 25 64 0a
printf(L"򦐥",v); // Unicode code point U+A6425

One way to print a single widechar is built in to printf as the %C format specifier (%lc for "long char" should be preferred in practical code). It requires a locale, so use setlocale(6) somewhere earlier in the program (LC_ALL as defined in limits.h should be preferred over 6 in practical code).

// print a spade card given by its index
printSpade(i){printf("%C",L"🂡🂢🂣🂤🂥🂦🂧🂨🂩🂪🂫🂭🂮"[i]);}
// print "🂭🂡"
main(){setlocale(6);printSpade(11);printSpade(0);}

Declare library functions directly

Standard library functions can be used without declaration, but this implies that the function returns an int. To use other, incompatible return types, the function must be declared. Since a function declared with an empty parameter list can be called with arbitrary arguments, it's often shorter to declare the function directly instead of including a header file.

long atol();
// vs
#include<stdlib.h>

double pow();
// vs
#include<math.h>

Function declarations can also be combined with variable declarations.

double pow(),x,y,z;
long atol(),i,j;