
Having fun abusing the C language - ingve
http://faehnri.ch/have-fun/
======
bluetomcat
A lesser-known quirk about typedef is that syntactically, it is treated like
any other storage-class specifier (static, extern, register, auto). Since the
ordering of storage-class specifiers is insignificant to the rest of the
specifiers, it means that the following statements have the same effect:

    
    
        typedef int myint;
        int typedef myint;
    

The only difference here compared to a normal declaration is that the name
"myint" defines a type and not an "object" as per the standard.

~~~
nneonneo
I've been programming C for the better part of my life now, and I've _never_
seen this. Neat!

------
jasode
_> , subscripts are just adding to pointers, and since addition is
commutative, then so is the subscript operator. [...] A lot to unpack from
such little code, and plenty to learn._

It was over 25 years ago that I first came across the C language FAQ from the
Usenet group _comp.lang.c_ and it explained the "commutative property" of
array subscripts. (Online version here:
[http://c-faq.com/aryptr/joke.html](http://c-faq.com/aryptr/joke.html)).
Another similar stackoverflow Q&A has also been done:
[http://stackoverflow.com/questions/381542/with-c-arrays-
why-...](http://stackoverflow.com/questions/381542/with-c-arrays-why-is-it-
the-case-that-a5-5a)

Over the last 2 decades, I have _never_ needed the knowledge that the C
language lets you put a number outside the brackets instead of inside it.
Other than deciphering obfuscated C puzzles, I've never run across any real
world source code that took advantage of that syntactic quirk. So yes, I did
learn that trivia about array subscripts -- but it was useless knowledge.

~~~
bodyfour
The only time I've found it useful is making macros that expect an array a
little safer in C++. For example:

    
    
        #define count(array) (sizeof(array) / sizeof(0[array]))
    

...will conveniently cause a compile error if you accidentally pass in a
std::vector instead of an array.

~~~
jasode
Thanks for the heads up. Not suprisingly, a related stackoverflow q&a mentions
that macro and also another more convoluted one from Chromium that protects
against accidental pointers being passed:
[http://stackoverflow.com/a/1598827](http://stackoverflow.com/a/1598827)

------
nneonneo
The IOCCC ([http://www.ioccc.org](http://www.ioccc.org)) is probably one of my
favorite rabbit holes, since I program very frequently in C. I once fully
explained one of the entries (2006-sykes2) on StackOverflow, which was quite
educational for me: [http://stackoverflow.com/questions/15393441/obfuscated-c-
cod...](http://stackoverflow.com/questions/15393441/obfuscated-c-code-
contest-2006-please-explain-sykes2-c/15395030)

It's hard for me to pick a favorite, but perhaps one of the most memorable is
2004-gavare:
[http://www.ioccc.org/2004/gavare.c](http://www.ioccc.org/2004/gavare.c). This
little gem implements a fairly sophisticated ray tracer using no C keywords or
preprocessor directives at all: no "int", "char", "if", "return", "#define",
etc. I learned a great deal about computer graphics (and, yes, C programming)
from reverse-engineering that program.

------
0xmohit
Thankfully trigraphs [0] aren't enabled in compilers such as gcc by default
else the following would print "oops":

    
    
      #include <stdio.h>
      int main() {
          if ('|' != '??!') {
              printf("ok");
          }
          else {
              printf("oops");
          }
          return 0;
      }
    

[0]
[https://en.wikipedia.org/wiki/Digraphs_and_trigraphs](https://en.wikipedia.org/wiki/Digraphs_and_trigraphs)

~~~
ufo
Didn't you mean != instead of == ?

~~~
0xmohit
Yes, indeed. Thanks, fixed.

------
stormbrew
If you ever want to give a c programmer a hard time, somehow sneak this into
one of their headers:

    
    
        #define struct union

~~~
raverbashing
Ah there are funnier, less obvious ways

~~~
stormbrew
I mean, as the sibling notes, there's redefining true as false, but I think
making all structs unions is much funnier, especially in that it's a uniquely
C proposition. There are other languages that allow redefinition of true and
false.

Also, I'm not sure how you think it's particularly obvious (as opposed to any
other #define trick). It does only work if the project isn't warning-safe, as
there are various ways this'll trigger ugly warnings (eg. using designated
initializer syntax causes re-initialization warnings), but even then the
warnings don't tend to actually tell you it's a union all of a sudden.

If you have others, I'd like to hear them.

~~~
raverbashing
\- Change the alignment of structs

\- Remember the order of includes change how they are applied. Have a #define
that changes something in a .h that's included in some files but not in others

\- (Depending on the software) redefine rand() to be almost predictable or
with a short loop

------
bcheung
You forgot

    
    
        char *main = [... assembly hex codes here ...]
    

I pissed off a CS teaching in high school doing that.

------
jejones3141
It should be

#define ELSE ;} else {

analogous to FI, to keep the appearance of semicolon as separator in the then
clause.

------
sigjuice
What do '\0', '\n', and '\9' mean?

~~~
ekimekim
These are escape sequences for non-printing characters. Well, the first two
are. '\9' would most likely cause a compile error, since that format
'\<digit>' is only defined for octal numbers, ie. digits 0-7.

'\0' means the NUL character, the value 0. Most of the time in C, this
character is a special terminator value at the end of strings.

'\n' means the newline character, aka the line feed character, ascii value 10,
which marks where one line ends and the next begins.

------
0xmohit
The following might be fun too:

    
    
      #define if while

------
mfukar

        subscripts are just adding to pointers, and since addition is commutative, then so is the subscript operator.
    

Only pointer arithmetic has nothing to do with integer arithmetic, a fact
which has bitten countless people in the ass over the years.

~~~
qwertyuiop924
No, pointer arithmetic has a lot to do with int arithmetic. And as in int
arithmetic, pointer arithmetic is commutative.

~~~
mfukar
Alright, yes, they share a property and the syntax. I forgot we were in a
programming courthouse.

In the real world, treating their semantics the same misleads newbies, and
leads to bugs.

~~~
tinus_hn
Yeah, who would do such a thing! Especially in a piece of code written for the
International Obfuscated C Code Contest! I demand that all code submitted for
that contest be readable and unobfuscated!

~~~
mfukar
Go vent someplace else.

