Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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.

share|improve this question
1  
+1,I really appreciate your initiative! :) –  Quixotic Apr 26 '11 at 12:27

20 Answers 20

Use bitwise XOR to check for inequality between integers:

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

share|improve this answer
    
+1,I love this one. –  Quixotic Apr 26 '11 at 12:15
25  
a-b gives you the same effect. –  ugoren Jan 12 '12 at 16:16
1  
Similarly 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 Jun 9 '12 at 16:35
  • 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!)

share|improve this answer

The comma operator can be used to execute multiple statements 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

share|improve this answer
10  
Pedantry: expressions. Not all statements are expressions; those which aren't won't work, e.g. variable declarations and control structures. –  Delan Azabani May 26 '12 at 9:30

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.

share|improve this answer
2  
Technically it's not valid according to standards as main accepts zero or two parameters, not one. Not that anyone cares in code golf. –  xfix Jan 2 at 22:24

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.

share|improve this answer
    
Addition: If you only need an if, but not an else then the ternary can still be useful. –  Casey Apr 27 '11 at 20:29
2  
&& 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 Jan 12 '12 at 16:20
1  
I'd never realized that gcc's ?: yields an lvalue. Can I use that in production code? lol –  Jeff Burdges Jan 12 '12 at 19:55
1  
@ugoren: x==3&&f() can be further golfed to x^3||f() –  fgrieu Dec 26 '12 at 12:04
    
@fgrieu, yes, though it's not exactly the topic here (this answer suggests it). –  ugoren Dec 26 '12 at 17:25

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

share|improve this answer

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.

share|improve this answer
    
Or just x+y*2, saving yet another char. –  B1KMusic Feb 2 at 8:29
1  
@B1KMusic, x+y*2 isn't the same, due to operator precedence. –  ugoren Feb 2 at 12:13
    
Right, lol. That would be x+(y*2). I was fixated on the x+y<<1 example, assuming it was being evaluated as x+(y<<1), and suggested the *2 instead. I didn't know bitshift operations were evaluated as e.g. (x+y)<<2 –  B1KMusic Feb 3 at 2:46

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.

share|improve this answer
4  
In this example, b-=a=b is even shorter. The ?: trick is still helpful, -= because also has low preference. –  ugoren May 8 '12 at 7:30
    
Good point; my example was needlessly complex. –  breadbox May 8 '12 at 8:54
    
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 May 8 '12 at 10:44

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

#define return R

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.

share|improve this answer

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   
share|improve this answer
    
The last tip ((x/y) == (x>=y)) is really useful. –  ugoren Sep 6 '12 at 9:11

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.

share|improve this answer

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.

share|improve this answer
    
What do you mean by in each step basis ? –  Casey Apr 26 '11 at 14:46
    
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 May 27 '11 at 13:34
    
Joey is right, I meant the same,sorry I didn't checked my inbox until today. –  Quixotic May 27 '11 at 18:52

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.

int p = sbrk(sizeof(whatever)) - m;
strcpy(m+p, "hello world");
share|improve this answer

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  */
share|improve this answer
  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]);}

share|improve this answer
    
Actually, 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 Dec 22 '13 at 21:21

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);
}
share|improve this answer

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(
share|improve this answer
5  
The 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 May 8 '12 at 7:25

I think the biggest single-sentence hint is: Read the winning codes submitted to IOCCC.

share|improve this answer

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);
share|improve this answer
3  
It 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 Dec 17 '13 at 2:51
    
@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 Dec 17 '13 at 14:05
  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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.