Tips for golfing in C

141

65

What general tips do you have for golfing in C? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to C (e.g. "remove comments" is not an answer). Please post one tip per answer. Also, please include if your tip applies to C89 and/or C99 and if it only works on certain compilers.

Casey

Posted 2011-04-24T01:04:28.663

Reputation: 3 129

9I think the biggest single-sentence hint is: Read the winning codes submitted to IOCCC. – vsz – 2012-05-12T21:23:52.903

Answers

111

Use bitwise XOR to check for inequality between integers:

if(a^b) instead of if(a!=b) saves 1 character.

Lowjacker

Posted 2011-04-24T01:04:28.663

Reputation: 4 466

22Similarly you can use a*b instead of a&&b (has different precendence, may or may not be bad). If you know a /= -b (e.g. they are unsigned) then a||b == a+b – walpen – 2012-06-09T16:35:44.667

3better yet combine it with the Elvis Operator ?: (instead of if) : for exemple to just do something if differents: a^b?_diff_:; – Olivier Dulac – 2016-12-24T08:52:26.597

1@OlivierDulac Is there a compiler that accepts an empty ternary if false branch? – Jonathan Frech – 2018-05-04T10:50:26.043

1@OlivierDulac You can check. From what I know, GCC has a ?: operator which is just equivalent to a ? a : b – Chromium – 2018-06-22T02:58:54.297

73a-b gives you the same effect. – ugoren – 2012-01-12T16:16:12.870

77

  • Abuse main's argument list to declare one or more integer variables:

    main(a){for(;++a<28;)putchar(95+a);}
    

    (answer to The alphabet in programming languages)

    This solution also abuses the fact that a (a.k.a. argc) starts out as 1, provided the program is called with no arguments.

  • Use global variables to initialize things to zero:

    t[52],i;main(c){for(;i<52;)(c=getchar())<11?i+=26:t[i+c-97]++;
    for(i=27;--i&&t[i-1]==t[i+25];);puts(i?"false":"true");}
    

    (answer to Anagram Code Golf!)

Joey Adams

Posted 2011-04-24T01:04:28.663

Reputation: 9 929

There are no data types defined for variables, no return type of main function. Is this valid C syntax? – Pavitra – 2020-01-07T10:23:53.063

2

@Pavitra : yes, this is commonly known as the "pre-ANSI" or "K&R" C variant. A variable without a type declared explicitly is an int. This has since been deprecated and all variables and functions are required to be declared with a type.

– Daniel Kamil Kozar – 2020-01-23T20:44:39.873

65

The comma operator can be used to execute multiple expressions in a single block while avoiding braces:

main(){                                                                                     

int i = 0;                                                                                  
int j = 1;                                                                                  
if(1)                                                                                       
    i=j,j+=1,printf("%d %d\n",i,j); // multiple statements are all executed                                                  
else                                                                                        
    printf("failed\n");                                                                     

}

Outputs: 1 2

Casey

Posted 2011-04-24T01:04:28.663

Reputation: 3 129

Doesn't work if one of the statements is break. – Maxim Mikhaylov – 2017-04-08T02:46:53.330

10@MaxLawnboy because break is a statement, and this answer is talking about expressions. – NieDzejkob – 2018-02-05T16:25:17.037

61

Avoid catastrophic function-argument type declarations

If you're declaring a function where all five arguments are ints, then life is good. you can simply write

f(a,b,c,d,e){

But suppose d needs to be a char, or even an int*. Then you're screwed! If one parameter is preceded by a type, all of them must be:

f(int a,int b,int c,int*d,int e){

But wait! There is a way around this disastrous explosion of useless characters. It goes like this:

f(a,b,c,d,e) int *d; {

This even saves on a standard main declaration if you need to use the command-line arguments:

main(c,v)char**v;{

is two bytes shorter than

main(int c,char**v){

I was surprised to discover this, as I have not so far encountered it on PPCG.

feersum

Posted 2011-04-24T01:04:28.663

Reputation: 29 566

1Note that using K&R features and newer (say '99) features together nay or may not be possible. Depends on your compiler. – dmckee --- ex-moderator kitten – 2015-05-17T17:47:48.513

5@dmckee is right. C99 does not allow implicit int, so you have to use -std=gnu99 and now you're not portable. In clc-speak, you're not even writing "C" code per se, but "Gnu99-C". 'Round here we mostly ignore that, but it's good to mention it if you post code that is compiler-specific. Sometimes people actually do download and execute these programs of ours. :) – luser droog – 2015-07-13T20:58:38.393

@luserdroog: You can use -std=c89 to tell gcc or clang to compile your code according to that older standard, which does allow implicit int with only a warning. – Peter Cordes – 2018-06-14T15:09:18.620

Quite often I've found that main(char*s,int**a) is the shortest declaration. s=*++a will still work as expected, as sizeof(int*) == sizeof(char*). – primo – 2020-02-21T10:02:52.620

6Why on Earth does that work?? – Nathaniel – 2014-10-24T08:41:54.970

31Apparently this is called K&R style and it precedes ANSI C by a decade. – Dennis – 2014-10-24T13:59:44.877

38

Instead of >= and <= you can simply use integer division (/) when the compared values are above zero, which saves one character. For example:

putchar(c/32&&126/c?c:46); //Prints the character, but if it is unprintable print "."

Which is of course still shrinkable, using for example just > and ^ (a smart way to avoid writing && or || in some cases).

putchar(c>31^c>126?c:46);

The integer division trick is for example useful to decide whether a number is less than 100, as this saves a character:

a<100 vs 99/a

This is also good in cases when higher precedence is needed.

Fors

Posted 2011-04-24T01:04:28.663

Reputation: 3 020

You can write putchar(c>31&c<127?c:46); – Jin X – 2019-02-24T19:33:42.123

38

Certain compilers, such as GCC, allow you to omit basic #includes, param, and return types for main.

The following is a valid C89 and C99 program that compiles (with warnings) with GCC:

main(i) { printf("%d", i); }

Notice that the #include for stdio.h is missing, the return type for main is missing, and the type declaration for i is missing.

Casey

Posted 2011-04-24T01:04:28.663

Reputation: 3 129

18Technically it's not valid according to standards as main accepts zero or two parameters, not one. Not that anyone cares in code golf. – Konrad Borowski – 2014-01-02T22:24:10.450

@NisseEngström: the calling conventions on mainstream C implementations make it safe to call variadic functions without prototypes. So most C implementations do define the behaviour. – Peter Cordes – 2018-06-14T15:12:53.847

Calling printf() (or any variadic function) without a prototype causes undefined behaviour. GCC does not compile standard C by default. If you invoke gcc in C89 mode (gcc -ansi -pedantic) or C99 mode (gcc -std=c99 -pedantic), you will get quite a few complaints, at least in the latter case. – Nisse Engström – 2014-10-27T13:31:17.417

30

The ternary conditional operator ?: can often be used as a stand in for simple if--else statements at considerable savings.

Unlike the c++ equivalent the operator does not formally yield an lvalue, but some compilers (notably gcc) will let you get away with it, which is a nice bonus.

dmckee --- ex-moderator kitten

Posted 2011-04-24T01:04:28.663

Reputation: 2 726

4@ugoren: x==3&&f() can be further golfed to x^3||f() – fgrieu – 2012-12-26T12:04:39.110

@fgrieu, yes, though it's not exactly the topic here (this answer suggests it).

– ugoren – 2012-12-26T17:25:33.377

In Objective-C I used it lot many time. Simplifies code as well – byJeevan – 2016-10-18T06:50:56.150

Addition: If you only need an if, but not an else then the ternary can still be useful. – Casey – 2011-04-27T20:29:47.820

9&& and || can also be used: if(x==3)f() becomes with your suggestion x==3?f():0, and can be further improved to x==3&&f(). But be careful with operator precedence - if f() is replaced with y=1, then the && solution requires an extra set of parenthesis. – ugoren – 2012-01-12T16:20:39.807

1I'd never realized that gcc's ?: yields an lvalue. Can I use that in production code? lol – Jeff Burdges – 2012-01-12T19:55:06.007

27

http://graphics.stanford.edu/~seander/bithacks.html

Bits are nice.

~-x = x - 1
-~x = x + 1

But with different precedences, and don't change x like ++ and --. Also you can use this in really specific cases: ~9 is shorter than -10.

if(!(x&y)) x | y == x ^ y == x + y
if(!(~x&y)) x ^ y == x - y

That's more esoteric, but I've had occassion to use it. If you don't care about short-circuiting

x*y == x && y
if(x!=-y) x+y == x || y

Also:

if(x>0 && y>0) x/y == x>=y   

walpen

Posted 2011-04-24T01:04:28.663

Reputation: 3 237

5The last tip ((x/y) == (x>=y)) is really useful. – ugoren – 2012-09-06T09:11:46.040

25

Use lambdas (unportable)

Instead of

f(int*a,int*b){return*a>*b?1:-1;}
...
qsort(a,b,4,f);

or (gcc only)

qsort(a,b,4,({int L(int*a,int*b){a=*a>*b?1:-1;}L;}));

or (llvm with blocks support)

qsort_b(a,b,4,^(const void*a,const void*b){return*(int*)a>*(int*)b?1:-1;});

try something like

qsort(a,b,4,"\x8b\7+\6\xc3");

...where the quoted string contains the machine language instructions of your "lambda" function (conforming to all platform ABI requirements).

This works in environments in which string constants are marked executable. By default this is true in Linux and OSX but not Windows.

One silly way to learn to write your own "lambda" functions is to write the function in C, compile it, inspect it with something like objdump -D and copy the corresponding hex code into a string. For example,

int f(int*a, int*b){return *a-*b;}

...when compiled with gcc -Os -c for a Linux x86_64 target generates something like

0:   8b 07                   mov    (%rdi),%eax
2:   2b 06                   sub    (%rsi),%eax
4:   c3                      retq

GNU CC goto:

You can call these "lambda functions" directly but if the code you're calling doesn't take parameters and isn't going to return, you can use goto to save a few bytes. So instead of

((int(*)())L"ﻫ")();

or (if your environment doesn't have Arabic glyphs)

((int(*)())L"\xfeeb")();

Try

goto*&L"ﻫ";

or

goto*&L"\xfeeb";

In this example, eb fe is x86 machine language for something like for(;;); and is a simple example of something that doesn't take parameters and isn't going to return :-)

It turns out you can goto code that returns to a calling parent.

#include<stdio.h>
int f(int a){
 if(!a)return 1;
 goto*&L"\xc3c031"; // return 0;
 return 2; // never gets here
}
int main(){
 printf("f(0)=%d f(1)=%d\n",f(0),f(1));
}

The above example (might compile and run on Linux with gcc -O) is sensitive to the stack layout.

EDIT: Depending on your toolchain, you may have to use the -zexecstack compile flag.

If it isn't immediately apparent, this answer was mainly written for the lols. I take no responsibility for better or worse golfing or adverse psychological outcomes from reading this.

ceilingcat

Posted 2011-04-24T01:04:28.663

Reputation: 5 503

3

I've just written a script to read parts of a C function from standard in and print a C lambda. Might be worth mentioning in your answer, might just be nice for you to see since you taught me to do this in the first place.

– MD XF – 2018-02-03T01:24:25.397

23

Define parameters instead of variables.

f(x){int y=x+1;...}

f(x,y){y=x+1;...}

You don't need to actually pass the second parameter.

Also, you can use operator precedence to save parenthesis.
For example, (x+y)*2 can become x+y<<1.

ugoren

Posted 2011-04-24T01:04:28.663

Reputation: 16 527

Or just x+y*2, saving yet another char. – Braden Best – 2014-02-02T08:29:44.787

5@B1KMusic, x+y*2 isn't the same, due to operator precedence. – ugoren – 2014-02-02T12:13:50.177

1Right, lol. That would be x+(y2). I was fixated on the x+y<<1 example, assuming it was being evaluated as x+(y<<1), and suggested the `2instead. I didn't know bitshift operations were evaluated as e.g.(x+y)<<2` – Braden Best – 2014-02-03T02:46:49.013

23

Use cursors instead of pointers. Snag the brk() at the beginning and use it as a base-pointer.

char*m=brk();

Then make a #define for memory access.

#define M [m]

M becomes a postfix * applied to integers. (The old a[x] == x[a] trick.)

But, there's more! Then you can have pointer args and returns in functions that are shorter than macros (especially if you abbreviate 'return'):

f(x){return x M;} //implicit ints, but they work like pointers
#define f(x) (x M)

To make a cursor from a pointer, you subtract the base-pointer, yielding a ptrdiff_t, which truncates into an int, losses is yer biz.

char *p = sbrk(sizeof(whatever)) - m;
strcpy(m+p, "hello world");

This technique is used in my answer to Write an interpreter for the untyped lambda calculus.

luser droog

Posted 2011-04-24T01:04:28.663

Reputation: 4 535

21

The ternary operator ?: is unusual in that it has two separate pieces. Because of this, it provides a bit of a loophole to standard operator precedence rules. This can be useful for avoiding parentheses.

Take the following example:

if (t()) a = b, b = 0;  /* 15 chars */

The usual golfing approach is to replace the if with &&, but because of the low precedence of the comma operator, you need an extra pair of parentheses:

t() && (a = b, b = 0);  /* still 15 chars */

The middle section of the ternary operator doesn't need parentheses, though:

t() ? a = b, b = 0 : 0;  /* 14 chars */

Similar comments apply to array subscripts.

breadbox

Posted 2011-04-24T01:04:28.663

Reputation: 6 893

7In this example, b-=a=b is even shorter. The ?: trick is still helpful, -= because also has low preference. – ugoren – 2012-05-08T07:30:24.660

Good point; my example was needlessly complex. – breadbox – 2012-05-08T08:54:58.397

Another point is that sometimes you want to flip the condition: for x>0||(y=3), x>0?0:(y=3) is useless, but x<1?y=3:0 does the job. – ugoren – 2012-05-08T10:44:37.647

both clang and gcc allow for an empty true case in the ternary. If omitted, its value is the value of the condition. For example, x>5?:y=1 – Chris Uzdavinis – 2019-04-09T04:56:44.817

20

Since usually EOF == -1, use the bitwise NOT operator to check for EOF: while(~(c=getchar())) or while(c=getchar()+1) and modify value of c at every place

Lowjacker

Posted 2011-04-24T01:04:28.663

Reputation: 4 466

1I don't know C well enough, but wouldn't while(1+c=getchar()) work? – ɐɔıʇǝɥʇuʎs – 2015-05-04T16:33:48.133

6@ɐɔıʇǝɥʇuʎs No. The addition operator + has higher precedence than the assignment operator =, so 1+c=getchar() is equivalent to (1+c)=getchar(), which does not compile because (1+c) is not an lvalue. – user12205 – 2015-05-19T18:56:15.650

19

Any part of your code that repeats several times is a candidate for replacement with the pre-processor.

#define R return

is a very common use case if you code involves more than a couple of functions. Other longish keywords like while, double, switch, and case are also candidates; as well as anything that is idomatic in your code.

I generally reserve uppercase character for this purpose.

dmckee --- ex-moderator kitten

Posted 2011-04-24T01:04:28.663

Reputation: 2 726

1A shorter replacement would be -DR=return. Note that if you include certain characters, it may become necessary to have single or double quotes around the define -DP='puts("hello")'. – None – 2018-07-25T18:29:11.620

15

If your program is reading or writing on one in each step basis always try to use read and write function instead of getchar() and putchar().

Example (Reverse stdin and place on stdout)

main(_){write(read(0,&_,1)&&main());}

Exercise:Use this technique to get a good score here.

Quixotic

Posted 2011-04-24T01:04:28.663

Reputation: 2 199

8That stack manipulation is gorgeous. – Andrea Biondo – 2015-05-21T19:53:46.763

What do you mean by in each step basis ? – Casey – 2011-04-26T14:46:58.813

Casey: I guess they mean if the program is reading something, operates on it, and writes output. In a streaming manner, so to say. As opposed to an approach where all the input has to be read and handled at once. – Joey – 2011-05-27T13:34:12.120

Joey is right, I meant the same,sorry I didn't checked my inbox until today. – Quixotic – 2011-05-27T18:52:22.500

15

Reverse Loops

If you can, try to replace

for(int i=0;i<n;i++){...}

with

for(int i=n;i--;){...}

ceilingcat

Posted 2011-04-24T01:04:28.663

Reputation: 5 503

14

If you ever need to output a single newline character (\n), don't use putchar(10), use puts("").

user12205

Posted 2011-04-24T01:04:28.663

Reputation: 8 752

12

Assign instead of return.

This is not really standard C, but works with every compiler and CPU that I know of:

int sqr(int a){return a*a;}

has the same effect as:

int sqr(int a){a*=a;}

Because the first argument is stored into the same CPU register as the return value.

Note: As noted in one comment, this is undefined behaviour and not guaranteed to work for every operation. And any compiler optimization will just skip over it.

X-Macros

Another useful feature: X-Macros can help you when you have a list of variables and you need to do some operation which involve all of them:

https://en.wikipedia.org/wiki/X_Macro

G B

Posted 2011-04-24T01:04:28.663

Reputation: 11 099

3I quoted this and I was corrected, This is simply not true. It will only work with multiplications and divisions and when optimizations are turned off. This is because both operations happen to put their results in eax which is the common register for return. Parameters are stored either in the stack or ecx or edx. Try it yourself. – Gaspa79 – 2017-04-09T20:15:13.873

3You are right, it's undefined behaviour, it also depends on the compiler and on the architecture, I usually check with gcc on x86 and armv7 before posting any answer using this trick. And of course if you enable optimization, any smart compiler would just delete the unnecessary multiplication. – G B – 2017-04-10T06:25:54.890

3I've seen this work with GCC but not others – Albert Renshaw – 2017-05-21T07:10:55.523

1

@Gaspa79: gcc with -O0 always chooses to evaluate expressions in the return-value register. I've looked at x86, ARM, and MIPS at least (on http://gcc.godbolt.org/), and gcc seems to go out of its way to do that at -O0. But remember if you take advantage of this, **the language you're programming in is gcc -O0, not C, and you should label your answer accordingly, not as C**. It fails at any optimization level other than -O0 debug mode, and doesn't work with clang IIRC.

– Peter Cordes – 2018-06-14T15:18:07.953

12

Make use of return values to zero stuff. If you call some function, and that function returns zero under normal conditions, then you can place it in a location where zero is expected. Likewise if you know the function will return non-zero, with the addition of a bang. After all, you don't do proper error handling in a code golf in any case, right?

Examples:

close(fd);foo=0;   →  foo=close(fd);    /* saves two bytes */
putchar(c);bar=0;  →  bar=!putchar(c);  /* saves one byte  */

MvG

Posted 2011-04-24T01:04:28.663

Reputation: 726

11

  1. Use *a instead of a[0] for accessing the first element of an array.

  2. Relational operators (!=, >, etc.) give 0 or 1. Use this with arithmetic operators to give different offsets depending on whether the condition is true or false: a[1+2*(i<3)] would access a[1] if i >= 3 and a[3] otherwise.

es1024

Posted 2011-04-24T01:04:28.663

Reputation: 8 953

11a[i<3?3:1] is two characters shorter than a[1+2*(i<3)]. – Reto Koradi – 2015-06-13T04:15:28.000

10

You may look into the IOCCC archives (international obfuscated C code contest).

One notable trick is to #define macros whose expansion has unbalanced braces/parentheses, like

#define P printf(

Andreas Krey

Posted 2011-04-24T01:04:28.663

Reputation: 101

16The mismatched parentheses have no value in themselves. The point is to define as much of the repeating pattern as possible. You might want to go further, with #define P;printf(. – ugoren – 2012-05-08T07:25:29.283

How does this shorten byte count? Perhaps provide an example? – Cyoce – 2016-09-19T05:07:59.377

2

@Cyoce See for example this answer.

– Jonathan Frech – 2018-04-30T12:56:31.990

8

Use for rather than while

Any while can be changed into a for of the same length:

while(*p++)
for(;*p++;)

On its own, that's not golf. But we now have an opportunity to move an immediately-preceding statement into the parens, saving its terminating semicolon. We might also be able to hoist an expression statement from the end of the loop; if the loop contained two statements, we could also save the braces:

a=5;while(*p++){if(p[a])--a;++b;}

for(a=5;*p++;++b)if(p[a])--a;

Even do...while loops should be replaced with for loops. for(;foo,bar,baz;); is shorter than do foo,bar;while(baz);.

Toby Speight

Posted 2011-04-24T01:04:28.663

Reputation: 5 058

8

for(int i=0;i<n;i++){a(i);b(i);} can be made shorter a few ways:

for(int i=0;i<n;){a(i);b(i++);} -1 for moving the ++ to the last i in the loop

for(int i=0;i<n;b(i++))a(i); -3 more for moving all but one statement into the top and out of the main loop, removing the braces

MegaTom

Posted 2011-04-24T01:04:28.663

Reputation: 3 787

1Using the comma operator is another way to avoid braces in some cases. – Peter Cordes – 2018-06-14T15:22:40.480

8

Go functional!

If you can reduce your problem to simple functions with the same signature and defined as single expressions, then you can do better than #define r return and factor-out almost all of the boilerplate for defining a function.

#define D(f,...)f(x){return __VA_ARGS__;}
D(f,x+2)
D(g,4*x-4)
D(main,g(4))

Program result is its status value returned to the OS or controlling shell or IDE.

Using __VA_ARGS__ allows you to use the comma operator to introduce sequence points in these function-expressions. If this is not needed, the macro can be shorter.

#define D(f,b)f(x){return b;}

luser droog

Posted 2011-04-24T01:04:28.663

Reputation: 4 535

7

Try cpow() instead of cos()

Instead of

double y=cos(M_PI*2*x);

try something like

double y=cpow(-1,x*2);

This uses Euler's formula, a little complex analysis and the observation that assigning a complex to a double yields the real part (careful with variadic function calls and other subtleties).

\$\cos 2\pi x+j\sin 2\pi x=e^{j2\pi x}=e^{j\pi 2x}=\left(-1\right)^{2x}\$

This type of trick can be used to reduce

double y=cpow(-1,x/2);

into

double y=cpow(1i,x);

because \$\left(-1\right)^\frac{x}{2}=j^\frac{2x}{2}=j^x\$

Edit: Equations now inline \$\LaTeX\$ instead of images.

ceilingcat

Posted 2011-04-24T01:04:28.663

Reputation: 5 503

7

Using asprintf() saves you the explicit allocating and also measuring the length of a string aka char*! This isn't maybe too useful for code golfing, but eases the everyday work with a char arrays. There are some more good advises in 21st Century C.

Usage example:

#define _GNU_SOURCE
#include <stdio.h>

int main(int argc, char** argv) {
  char* foo;
  asprintf(&foo, "%s", argv[1]);
  printf("%s",foo);
}

klingt.net

Posted 2011-04-24T01:04:28.663

Reputation: 876

7

  1. use scanf("%*d "); to read the dummy input. (in case that input is meaningless in further program) it is shorter than scanf("%d",&t); where you also need to declare the variable t.

  2. storing characters in int array is much better than character array. example.

    s[],t;main(c){for(scanf("%*d ");~(c=getchar());s[t++]=c)putchar(s[t]);}

Neeraj Gupta

Posted 2011-04-24T01:04:28.663

Reputation: 171

3Actually, I use %*d not only in Golf because it's also useful in situations where one would, for example, want to skip a newline in scanf("%[^\n]%*c",str); :) – tomsmeding – 2013-12-22T21:21:36.940

6

Print a character then carriage return, instead of:

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

or

putchar(c);putchar('\n'); // or its ascii value, whatever!

simply, declare c as an int and:

puts(&c);

moala

Posted 2011-04-24T01:04:28.663

Reputation: 221

9It is probably worth pointing out that this depends on a little-endian architecture. If c is a big-endian int, then you'll just get the carriage return. (On the other hand, if c is a char, you might get random garbage after instead of a carriage return.) – breadbox – 2013-12-17T02:51:24.393

@breadbox yep, you are totally right; I just edited: the last excerpt should use c as an int (which is frequently easy to declare as such). – moala – 2013-12-17T14:05:42.083

Does puts(&c) really work? That wouldn't necessarily be null-terminated. – Esolanging Fruit – 2018-01-16T05:40:27.750

1@EsolangingFruit On little-endian with 32-bit ints, an int 0 ≤ c < 256 is stored as the byte sequence c 0 0 0. When interpreter the address of c as char *, we see a singleton string: the character c, followed by a null byte. – Dennis – 2018-01-28T14:39:22.397

6

import if you have to

As noted in the very first answer, some compilers (notably, GCC and clang) let you get away with omitting #includes for standard library functions.

Even if you can't just remove the #include, there might be other ways to avoid it, but that's not always practical or particularly golfy.

In the remaining cases, you can use #import<header file> instead of #include<header file> to save a byte. This is a GNU extension and it is considered deprecated, but it works at least in gcc 4.8, gcc 5.1, and clang 3.7.

Dennis

Posted 2011-04-24T01:04:28.663

Reputation: 196 637

5

Here are a few tips I've used to my advantage. I've shamelessly stolen them from others, so credit to anyone but me:

Combine assignment with function calls

Instead of this:

r = /* Some random expression */
printf("%d", r);

Do this:

printf("%d", r = /* Some random expression */);

Initialize multiple variables together (when possible)

Instead of this:

for(i=0,j=0;...;...){ /* ... */ }

Do this:

for(i=j=0;...;...){ /* ... */ }

Collapse zero/nonzero values

This is a neat trick I picked up from someone here (don't remember who, sorry). When you have an integer value and you need to collapse it to either 1 or 0, you can use !! to do so easily. This is sometimes advantageous for other alternatives like ?:.

Take this situation:

n=2*n+isupper(s[j])?1:0; /* 24 */

You could instead do this:

n=n*2+!!isupper(s[j]); /* 22 */

Another example:

r=R+(memcmp(b+6,"---",3)?R:0); /* 30 */

Could be rewritten as:

r=R+R*!!memcmp(b+6,"---",3)); /* 29 */

Cole Cameron

Posted 2011-04-24T01:04:28.663

Reputation: 1 013

1maybe R*-~!!mxxxx – l4m2 – 2018-04-18T05:59:48.413

5

Knowing basic logical equalities might be able to save a couple bytes. For instance, instead of if (!(a&&b)){} try instead using DeMorgan's law if (!a||!b){}. The same applies to bitwise functions: instead of ~(a|b) do ~a&~b.

tox123

Posted 2011-04-24T01:04:28.663

Reputation: 158

Cf. De Morgan's laws.

– Jonathan Frech – 2019-09-13T01:07:07.097

4

Inverse flag update

Sometimes a challenge asks to determine a data set's specific boolean property. To avoid the unacceptably long return keyword, I often use a flag variable which gets updated in a loop and assign-returned at the end (I will refer to this tip for more detail on assign-returning).

When working with such boolean flags and boolean values, to update them I often use either f&=a|b or f*=a|b to align them with the result of a|b. This is equivalent to saying f = f && (a|b).

However, sometimes a flag needs to be inversely updated, meaning f = f && !(a|b). Naively, one would use f&=!(a|b) (9 bytes), or -- using fundamental logical equivalences -- one would golf it to f&=!a&!b (8 bytes).
For the case of an inverse flag update, though, one might be better off using the binary shift right operator >>, as the previous assignment is (when working with boolean values) equivalent to f>>=!(!a&!b), which simply golfs to f>>=a|b (7 bytes).

If the flag update in question does not involve parentheses due to negation (as in the previous example), inverse flag updating may still be shorter, as for example f&=!a|!b (8 bytes) is equivalent to f&=!(a&b) (9 bytes), which is equivalent to f>>=a&b (7 bytes).

Inverse flag updating may in certain cases also be used even though the values in question are not boolean (either 0 or 1).
If only one operand is boolean, bitwise and (&) can still be used, as the second operand's bits will all be cleared. When using bitwise or (|) or both operands are non-boolean, one should consider using logical and (&&) and logical or (||) to get a boolean result, even though they are one byte longer.

As a side node, these rules also apply when the expression is side-effect-dependent, meaning !f()&&!g() is equivalent to !(f()||g()) regarding the execution of g(), such that even in those cases inverse flag updating can be used.

For testing purposes, I wrote a simple truth table tester (TIO-link).

One recent real-world example of this technique in action would be for example my answer to Detect Rectangular Text.

Jonathan Frech

Posted 2011-04-24T01:04:28.663

Reputation: 6 681

4

Missing includes and return values

As noted in the very first answer, some compilers (notably, GCC anc clang) let you get away with omitting #includes for standard library functions.

While that usually goes well, it might cause problems in some cases, since the implicit declarations of standard library functions inside the source code will cause the compiler to treat return values as ints. For example, the code

char*p=getenv("PATH");

wont work as expected on a 64-bit platform since getenv returns a 64-bit memory address which doesn't fit into an int.

In this case, there are at least three ways to use getenv without errors.

  • Include the header file as follows.

    #include<stdlib.h>
    char*p=getenv("PATH");
    

    This is the right way™, but not very golfy; it costs 19 bytes.

  • Declare getenv with the pointer as follows.

    char*getenv(),*p=getenv("PATH");
    

    This costs 10 bytes.

  • Finally, unless your code wouldn't work on 32-bit platforms, compile your code on one of those or with the -m32 flag (gcc). This costs 0 bytes.

Dennis

Posted 2011-04-24T01:04:28.663

Reputation: 196 637

3

Use s[i] instead of i<strlen(s) in string-handling loops

For example:

for(i=0;i<strlen(s);i++)s[i]=s[i+1];

can be shortened to:

for(i=0;s[i];i++)s[i]=s[i+1];

MD XF

Posted 2011-04-24T01:04:28.663

Reputation: 11 605

3Though in this case one would most likely not bother with indices and use pointer incrementation; for(;*s;)*s=*++s;. – Jonathan Frech – 2018-04-30T12:59:14.237

3

Set an array of int to the same value (C99, Linux, BSD, OSX)

Instead of

int a[n]=...,x=...;
for(int i=n;i--;)a[i]=x

Try something like

int a[n]=...,x=...;
wmemset(a,x,n);

On MSVC on Windows, wmemset() works on arrays of short instead of int.

ceilingcat

Posted 2011-04-24T01:04:28.663

Reputation: 5 503

1Iirc wchar_t is 32 bits wide with gcc on Windows as well, unless you specify the -fshort-wchar flag. – Dennis – 2018-06-16T04:41:19.547

3

Boolean constant string selection when the selector's true value is guaranteed to be one larger than the second option's length

At its heart, this tip attempts to golf a ternary if of the form cnd?str_true:string_false when two conditions are met, namely that both str_true and string_false are constant strings and cnd is either 0 or strlen(string_false)+1.

If the above conditions are met, the expression cnd?"true":"false" can be golfed* by one byte to "false\0true"+cnd (here cnd == 0 || cnd == 6 always holds); another byte can be shaved off by not escaping the null byte (a compiler dependent feature).

The tip in action

For this example, suppose the string selection's criterion is k%3's truthiness, where k-1 is never divisible by three. In this case the ternary if

k%3?"°@°":"_" // 13 bytes

can be golfed to:

"_\0°@°"+k%3 // 12 bytes

Which can be golfed down to eleven bytes if one does not escape the null byte.

Application in obfuscation

As the above requirements are rather strict, this tip is most likely not widely applicable. Nonetheless, the shown technique can also be used to potentially obfuscate a program at no further byte cost.

Given e as a truly boolean expression -- (e) == 0 || (e) == 1 holds -- with the proper operator precedence regarding the upcoming factor, the following snippets are interchangeable* at the same byte count -- when not escaping the null byte.

e?"lifeless":"lychee"
"lychee\0lifeless"+e*7

Bare in mind that this obfuscation is only non-detrimental to the byte count if the second option's string is not longer than eight characters -- since else the factor spans more than one byte.

*: If interpreted as constant strings.

Jonathan Frech

Posted 2011-04-24T01:04:28.663

Reputation: 6 681

If the strings to be selected are two or fewer octets in length, you can use wide characters. L"AB"+p will return "A" if p==0 and "B" if p==1. – ceilingcat – 2018-11-24T17:43:09.993

3

instead of the printf loop

for(i=1;i<12;i++){if(!i%3)printf("\n");printf("%d",i);}

just use

for(i=1;i<12;i++) printf("%c%d",!(i%3)*10,i);

it helps me so much .


@SamHocevar 's answer (shoretr by 2bytes)

for(i=1;i<12;i++) printf("\n%d"+!!(i%3),i); 

Abr001am

Posted 2011-04-24T01:04:28.663

Reputation: 862

4The second line is incorrect; it will actually print the null characters. – sam hocevar – 2015-05-04T23:16:27.080

lol im not pinting them into char array , it is terminal console, and nul character doesnt mean space nor a newline:/ – Abr001am – 2015-05-04T23:39:47.647

8You can use this: printf("\n%d"+!!(i%3),i); which is 2 characters shorter. – sam hocevar – 2015-05-05T00:47:50.960

3

Use bitwise and (&) when comparing boolean expressions to save one byte.

Example:

if(i^2&k/3) DoSomething;

Really, really useful when combined with the other tips

takra

Posted 2011-04-24T01:04:28.663

Reputation: 793

2The example if(i^2&k/3) seems like it would be equivalent to if(i != 2 && k >= 3), but it's not because & has higher precedence than ^. Also, even if(i-2&k/3) wouldn't work, because a bitwise and of two nonzero values could result in zero. On the other hand, if(i!=2&k>2) would work. – user59468 – 2016-09-19T23:44:33.610

2

Swap variables

If you ever need to swap variables, don't use the pattern with an extra variable or that addition-subtraction-method, just do some chained XORing:

a^=b^=a^=b;

Karl Napf

Posted 2011-04-24T01:04:28.663

Reputation: 4 131

2

This is undefined behavior, due to a lack of sequence points in between two modifications of the same object. See here: https://stackoverflow.com/questions/9958514/sequence-point-xor-swap-on-array-get-wrong-result

– 2501 – 2017-04-23T19:44:22.873

2

Overload functions (unportable)

Instead of declaring multiple functions...

d(x){return x*2;}
float r(float x){return 1/sqrt(x);}
...
printf( "%d %f\n", d(2), r(2) );

...declare one "function" that does different things depending on return and parameter types.

(*f)()=L"\xf33f048d\xc3c0520f"; // global
...
printf( "%d %f\n", f(2), ((float(*)(float))f)(2) );

Try it online! This works because some ABI's (Linux x86_64, in this example) use separate registers for floating point and integer arguments and return values.

The disassembly of the (*f)() "function"...

0:       8d 04 3f                lea    (%rdi,%rdi,1),%eax
3:       f3 0f 52 c0             rsqrtss %xmm0,%xmm0
7:       c3                      retq

On a x86_64 Linux machine, this function takes the first integer parameter, doubles it and places the result in %eax (char/short/int/long return value). It takes the first floating point parameter, computes a low precision reciprocal square root and places it in %xmm0 (float/double return value).

ceilingcat

Posted 2011-04-24T01:04:28.663

Reputation: 5 503

This would be a better answer if you decoded the x86 asm in a comment or something, and also link to a method for turning hand-written asm into strings. I don't want to go look up an opcode table. I can see it ends with a c3 RET (x86 being little-endian), but I can only guess that the other bytes are lea eax, [rdi+rdi] and rsqrtps xmm0,xmm0 (with no Newton iteration? that's very inaccurate...), because that's what would make sense. – Peter Cordes – 2018-06-14T15:37:43.767

2

Use #define instead of functions when possible

For example:

f(int i,char*s){/*do something with i and s*/;}

Using #define can eliminate the argument list type, curly-braces and closing semicolon:

#define f(i,s)/*do something with i and s*/

MD XF

Posted 2011-04-24T01:04:28.663

Reputation: 11 605

2

Inline arrays

If you need a non-int constant array and just use it once, you can do

float f(a){return (float[]){.3,.2,.7}[a];}

instead of

float z[]={.3,.2,.7};float f(a){return z[a];}

to save 3 bytes.

(In this case it can save one more byte since the blank after return can be omitted.)

Colera Su

Posted 2011-04-24T01:04:28.663

Reputation: 2 291

2

Whenever a certain function is called several times, it's common to #define it to something shorter. However, certain compilers (MinGW and clang as far as I know) allows for something even more compact by using function pointers:

(*P)()=printf;
P("Test: %d\n", 10);

Other compilers might require an #include of the proper header file for it to work.

gastropner

Posted 2011-04-24T01:04:28.663

Reputation: 3 264

2

Get the length of a string with puts() instead of strlen()

According to the standard C specification, puts() returns a non-negative integer on success. In practice, most C libraries seem to treat puts(s) as equivalent to printf("%s\n", s), which returns an integer equal to the number of bytes written.

As a result, the return value of puts(s) is equal to 1 + strlen(s). If the additional console output can be ignored, this saves a few bytes.

r3mainer

Posted 2011-04-24T01:04:28.663

Reputation: 19 135

"a few" in this case is 4. – Jonathan Frech – 2019-09-13T01:04:39.103

2

Calculating \$\lceil\log_{10}(n)\rceil\$

Especially in challenges where properties of decimal representations are of interest, one needs to find a number's decimal representation's length, or for \$n\in\mathbb{N}^+\$ equivalently, \$\lceil\log_{10}(n)\rceil\$.
In this post, several approaches are presented and discussed.

For a C source file containing approaches (a.1) to (b.3) together with a testing setup, see TIO.

I wrote this tip based on this answer of mine, searching for a smaller approach than (a.1).
If you know of any other approach possibly shorter in even a specific scenario, feel free to either add your own tip or add to the list below.

(a.1) An expression in n, 20 bytes

snprintf(0,0,"%d",n)

Versatility is a great property of the above approach, when used to determine a number's decimal representation's length, the most direct approach might be the most byte-effective.

0 is given its correct decimal representation length of 1.

GCC only throws a warning for ignoring #include <stdio.h>, otherwise the inclusion would be very byte-heavy at potentially 19+20=39 bytes. If instead of sprintf(0, one uses sprintf(NULL, the byte count is increased to 23 bytes. If using both, the byte count could jump to 42 bytes.

(a.2) A function in n, 29 bytes

a(n){n=snprintf(0,0,"%d",n);}

By being a function, this approach's versatility is high; (a.1)'s compiler-specifics also apply, when properly returning, the byte count increases to 5+29=34 bytes.

0 is given its correct decimal representation length of 1.

(b.1) A function in n, requiring another variable, 32 bytes

b(n,k){for(k=0;n;k++)n/=10;n=k;}

Of all approaches presented, this one has the worst byte count. However, considering potential compiler restrictions discussed in (a.1), it could prove more byte efficient, since the approach is nearer to the C core.

0 is given its incorrect decimal representation length of 0. One can make the case for defining \$\lceil-\infty\rceil:=0\$ which would make this approach closer to a logarithm implementation, when further defining \$\log(0):=-\infty\$.

Modification to calculate \$\lceil\log_b(n)\rceil\$ for a base \$b\in\mathbb{N}^+\$ is possible, changing the byte count by the bytes required to represent \$b\$ in C-source.

(b.2) A statement requiring existence of two variables, setting n=0, 20 bytes

for(k=0;n;k++)n/=10;

If another variable is already declared and n can be either discarded or needs to be cleared regardless and the use case is a whole block instead of a one-line expression, the above could be used. Since it is equivalent in byte count to (a.1), the behavioural differences have to be analyzed.

Minimally wrapped inside a function, it becomes (b.1), both being similar in features.

(b.3) A statement working additively on k, setting n=0, 17 (pot. 16) bytes

for(;n;k++)n/=10;

Another variation on (b.1), removing initialization of k. Furthermore, for(; leaves space for an expression, potentially allowing to save a semicolon's byte, effectively rendering this approach 16 bytes long.

(c.1) A statement in n, producing stdout-output, 14 bytes

printf("%d",n)

Courtesy of H.PWiz.

This approach's utter conciseness and simplicity may be alluring, its major drawback, however, is its stdout-output; tolerability being heavily challenge-dependent.

Jonathan Frech

Posted 2011-04-24T01:04:28.663

Reputation: 6 681

I suppose it's not alright for you to use printf, even when the submission is a function? – H.PWiz – 2019-09-13T01:11:34.963

As in returning the number of characters printed, ignoring output to stdout? – Jonathan Frech – 2019-09-13T01:13:12.020

Is there a standard null stream so that printf(stdnull,"%d",n) could be used? – Jonathan Frech – 2019-09-13T01:18:48.253

I have added it as (c.1). – Jonathan Frech – 2019-09-13T01:24:55.810

2

Exploit ASLR

On systems with ASLR (Address Space Layout Randomization), the address of a stack variable can be used as a one time pseudorandom number. Instead of something like...

srand(time(0));

...try something like

srand(&x)

...where the address of x (hopefully on the stack) is unique each time the program is run.

ceilingcat

Posted 2011-04-24T01:04:28.663

Reputation: 5 503

Hmm... Where have I seen this before? :) +1 – S.S. Anne – 2020-02-21T02:18:30.280

2

When you have to walk a string you can walk the pointer instead of incrementing the index.

Code :

#include <stdio.h>

// print each char
void f(char* s) {
    for (int i=0;s[i];i++) putchar(s[i]);
}

// same output than f;
void g(char* s)
{
    for (;*s;) putchar(*s++);
}

int main(void) {
    f("hello\n");
    g("hello\n");
    return 0;
}

example: Remove duplicated & switched case

aloisdg moving to codidact.com

Posted 2011-04-24T01:04:28.663

Reputation: 1 767

1

Sometimes, albeit rarely, if your code contains many for loops, #define F for( may save a byte or two (especially if some of the loops have an empty init section).

If it is applicable to your situation, #define F;for( may save even more bytes.

Examples:

https://codegolf.stackexchange.com/a/153117/61405

https://codegolf.stackexchange.com/a/149629/61405

Steadybox

Posted 2011-04-24T01:04:28.663

Reputation: 15 798

1

When your algorithm produces output in reverse order, take a pointer to the end of a buffer and write it in decreasing order, returning a pointer to the first element. It's up to the caller to supply a buffer large enough for any this input, or for any possible input.

Base conversion / int-to-string is a classic example where this interface is used in real life, such as glibc's internal _itoa, used by the printf family of functions as well as some other internal callers. The max buffer size is 65 bytes for a 64-bit integer -> base 2 string.

// takes a pointer to one-past-the-end, which is also a valid option.
char *itoa_end(unsigned long val, char *p_end) {
  // does *not* zero terminate the buffer.  Use *--p_end = 0;
  const unsigned base = 10;
  char *p = p_end;
  do {
    *--p = (val % base) + '0';
    val /= base;
  } while(val);                  // runs at least once to print '0' for val=0.    

  // write(1, p,  p_end-p);
  return p;  // let the caller know where the leading digit is
}

For golfing, it can be more compact to take the pointer by reference and modify it, instead of returning it. (return is a long keyword, and code depending on gcc -O0 evaluating expressions in the return-value register isn't even C.)

For example, I used this in ASCII art uncompression from a base-n number (i.e. int->string with a digit lookup table), where I already needed a char* arg, so it was very cheap to declare another as a char **.

Use *p everywhere you have p in the simple version. *--*p decrements the caller's pointer, then dereferences that to reference the actual character.

/* int n = the number
 * int B = size of I = base
 * char I[] = input table
 * char **O = input/output arg passed by ref:
 *    on entry: pointer to the last byte of output buffer.
 *    on exit:  pointer to the first byte of the 0-terminated string in output buffer
 */
void semi_golfed_g(n,I,B,O)char*I,**O;
{
    for(**O=0 ; n ; n/=B)
        *--*O = I[n%B];
}

Peter Cordes

Posted 2011-04-24T01:04:28.663

Reputation: 2 810

1

Use recursion over loops.

Recursive example

f(){printf("infiniteloop");f();}

For loop equivalent is 3 bytes longer.

f(){for(;;)printf("infiniteloop");}

Geo

Posted 2011-04-24T01:04:28.663

Reputation: 91

I think you are missing a semicolon in your recursive example. – Jonathan Frech – 2018-07-09T23:48:23.253

Do you have an example for a terminating program which could be golfed in this way? Or does this tip only apply to infinite loops? – Jonathan Frech – 2018-07-10T00:11:46.110

Yes, I actually have the shortest c solution in this example

– Geo – 2018-07-11T17:03:30.437

4f(){f(printf("infiniteloop"));} would save a further byte in this example. Try it online! – Dennis – 2018-09-23T04:49:43.127

1

Abuse two's complement

A lot of expressions can be changed by (ab)using two's complement. Take this for example:

getchar()+1

If you need higher precedence, you can use this:

-~getchar()

Or, if you're using it as the condition for a loop, this can be used:

~getchar()

Additionally, instead of subtracting one after another subtraction:

a+b-1

you can add the bitwise-NOT of the second operand:

a+~b

This applies similarly to multiplication by 2:

2*(a-b)-1

can be shortened to:

a-b+a+~b

S.S. Anne

Posted 2011-04-24T01:04:28.663

Reputation: 1 161

@ceilingcat oh, yeah. That explains why it didn't work in my head. But I wonder why it worked in the ASCII rocket challenge. – S.S. Anne – 2020-02-21T11:56:16.273

1

For scanning a string into an array, you can use

gets(str);

instead of

scanf("%s",str);

Spikatrix

Posted 2011-04-24T01:04:28.663

Reputation: 1 663

1Yeah, except you should never use gets. – MD XF – 2017-05-13T00:24:57.650

4@MDXF Welcome to code golf – DollarAkshay – 2018-03-31T17:17:21.810

3@MDXF: ... for the exact same reason you should never use "%s" instead of "%256s" as your scanf format string. (Or whatever the buffer size is.) – Peter Cordes – 2018-06-14T15:31:36.637