Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Post History

60%
+1 −0
Q&A Tips for golfing in C

For the sake of code golf, you first need to decide if you wish to compete in strictly conforming ("real") C, in which case you can't rely on non-standard extensions, poorly-defined behavior or obs...

posted 2y ago by Lundin‭

Answer
#1: Initial revision by user avatar Lundin‭ · 2021-08-10T14:24:49Z (over 2 years ago)
For the sake of code golf, you first need to decide if you wish to compete in strictly conforming ("real") C, in which case you can't rely on non-standard extensions, poorly-defined behavior or obsolete features.

Or you can compete in non-standard extensions (gcc/GNU etc), when whatever binary the compiler lets through with default settings is fair game - including those that may be abusing poorly-defined behavior.

List of tricks below:

- **Format of `main()`**  
  In strictly conforming hosted C, the form `int main()` is the most compact. Empty parenthesis is obsolete style but it has not yet been formally withdrawn. Alternatively two parameters can be used, normally named argv and argc though C allows us to rename them. In conforming C, we may not change their types however, so the most compact conforming version is:

  ```c
  int main(int c,char**v)
  ```

  (Or use compatible types.) `main(c,v)` is however not conforming.

  In conforming freestanding C, other forms of main() may be used, but that's for embedded systems and not likely applicable for code golf.

  In non-conforming/gcc extensions, old C90 style `main()` works.

  Note that `return 0;` is no longer necessary in main() as from C99 - omitting it is well-defined.

- **Format of functions.** Non-conforming K&R style functions are still supported by most compilers, for example:
  ```c
  f(a,b)int a;char b; 
  ```

  This can be handy when you need to declare parameters and local variables with the same type.

- **Abuse static storage duration.** Variables declared at file scope have static storage duration and are therefore guaranteed by the standard to be zero-initialized, saving the need to do such in code.

- **Abuse C90 implicit int.** In C90 and non-conforming gcc extensions you can declare a variable as `x;` and you get an `int`. Similarly, in C90 functions that declare no return type were assumed to return `int`.

- **Omit include files.** While not allowed in strict C, non-standard gcc allows to omit all `#include`. 

- **Always use for loops.** `for(;;)` is the most compact form. The first clause can be used for variable declarations, which is handy since you have to leave a semicolon there anyway. The 2nd and 3rd clauses can contain pretty much any code, such as a long list separated by `,` operator. In many cases you can place the whole program there and then end the line with `;`, no need for a loop body with `{}`.

- **Use recursion instead of loops.** Recursion can save a lot of overhead code, in case the equivalent loop has a suitable exit condition that needs to be there no matter.

- **Use `?:` instead of if-else.** It is far more compact and can be used to write long nested expressions in compact ways.

- **&& short circuit instead of if**. For example `if(foo)bar();` can often be written as `foo&&bar();`.

- **Mix ++ and -- with other expressions.** Contrary to good programming practice, this can save characters. For example `for(;;i--)printf("%d",a[i]);` could be written as `for(;;)printf("%d",a[i--]);`. Experiment with prefix and postfix versions too. Big chance that you end up with a non-conforming solution though.

- **`!` is generally handy**, for example when converting a non-zero value to 1, or to get boolean 1/0 out of expressions.

- **Use bitwise operators when possible**. `&&` and `||` can sometimes be replaced with `&` and `|`.

- **`^` xor instead of `!=`**.

- **`sizeof` doesn't need parenthesis if the operand is an expression**. Don't do `sizeof(expr)`, always do `sizeof expr`.

- **Pointer arithmetic instead of array indexing.**  `arr+n` not `arr[n]`.

- **Use `#` pre-processor stringification.** If you can afford a `#define` then everything inside it can be turned to string literals, which is handy if you have to repeat a lot of strings. Pre-processor string concatenation is also handy: `"foo" "bar"` will create "foobar". 

- **`int` can often be used instead of `char`** for storing characters.

- **Integer constants are more effective than character ones.** Use `char ch=32;` not `char ch=' '`.

- **Use binary arithmetic instead of larger numbers.** `~0` instead of `4294967296`. `1<<30` instead of 0x40000000. And so on.

- **X-macros are handy for avoiding repetition.** Particularly when listing data. One example here: https://codegolf.codidact.com/posts/279820/279856#answer-279856

- **Abuse the poor type system and endianess when printing strings.** Wildly non-conforming: `int x=65; puts(&x);` This prints the null terminated string `"A"`, since puts treats the raw binary on a 32 bit int little endian machine as hex `41 00 00 00`. This can also be handy for integer to string conversions where you already have the integer in memory.

- **Use `puts when possible`**. It is compact and saves you from printf with the burdensome format string. It also prints new line implicitly. And I've seen some other clever uses like `malloc(puts(s))` instead of `malloc(strlen(s)+1)`.

- **Use VLA**. Avoid malloc, use VLA instead. `int x[n];` beats `int*x=malloc(n);`

- **Use evil non-standard libs**. Some compilers support `gets`,`putch` and similar compact functions as non-standard extensions without the need to include special headers.