General
- Use single letter variable and function names
- Reuse variables where possible and useful
- Create own functions only where absolutely necessary. Put as much code into main as possible.
- Strip all unnecessary white spaces and newlines
- Include only absolutely necessary libraries (no "stdlib.h" and "stdio.h" for example!)
- Additional tips and tricks: tips-for-golfing-in-c
- If a thing like a string length never changes, use a constant value instead of strlen()
- If you need to use big constants like
10000
, write it in scientific notation as 1e4
.
- Initialize variables in the init part of a for-loop, to safe one
;
and not before a for-loop
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
- K&R-style syntax is used to declare the type of
v
, while leaving c
as implicit int
v
is declared as int**
instead of char**
. This works fine as long as we never index *v
or perform arithmetic on it
- The for loop is infinite and the program terminates when puts tries to read the null pointer past the end of
v
main(c,v)int**v;{for(;;)puts(*++v);}
print substrings with printf
You can print a substring with printf
in at least two ways:
- Dynamically, by adding a parameter with the number of characters, and after that the string to be cut.
- Or statically, with the number of characters to cut, embedded in the format string.
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;