
C99 tricks - guillaumec
http://blog.noctua-software.com/c-tricks.html
======
unwind
There's nothing "C99" about that ARRAY_SIZE macro, of course.

That said, I'm rather sceptical towards it, I think it's better written as-is.

Otherwise, the question "does SIZE mean bytes, or number of elements?" always
arises to haunt me. Once you need to keep looking stuff like that up, the
macro isn't helping.

In actual code, the name of the array never needs to be enclosed in
parentheses so it's often clearer too. E.g. something like:

    
    
        int fourk[4096];
    
        for(size_t i = 0; i < sizeof fourk / sizeof *fourk; ++i)
          ...
    

I realize that it's not 100% DRY to repeat the array name, but I think it's a
small price to pay for not having to use a non-standard macro that requires
learning. It's all about friction.

~~~
userbinator
I use the convention "size = number of bytes" (as in _size_ of), "count =
number of elements" and so my sizeof(x)/sizeof(x[0]) macro is actually called
COUNT.

~~~
clarry
In the BSDs (and some other code bases) the macro is spelled nitems and is
common enough to be considered idiomatic.

~~~
__david__
I always call my version lengthof() to match sizeof.

~~~
alnsn
I use lengthof for lengths of string literals.

------
pfortuny
Read the first comment in the comments section and get your mind blown away...
What can export restrictions do!

~~~
clarry
Ah, javascript and bad design breaking the web again. Disable JS and it'll be
fine.

(I had to enable JS to see the comments, and that caused me to see the very
same effect reported in the first comment)

~~~
gear54rus
> due to US sanctions

If that's true, blaming fabric of the web for this is ridiculous. Blame idiots
who went ahead with 'sanctions' on information.

------
kzrdude
These are GNU C tricks! Fine anyway, I think I especially like those that are
ISO C. Trick number one is a C11 feature -- anonymous struct members in
structs and unions, though I will not vouch for its validity without
consulting with my C11 standard handbook.

Oh, and by the way, why not use X macros in the form where the macro to apply
is passed as the argument? #define SPRITES(S) S(1, 2, 3) S(2, 3, 4) etc.

~~~
guillaumec
About the X: Yeah, that is stupid actually... I will update the article to
change it to X.

~~~
kzrdude
That's not what I meant! :-)

------
Genmutant
The first one (?:) is not standard but only a GNU extension, so be carefull
with that one.

~~~
guillaumec
Thanks for letting me know. I though this was in the standard. I will fix the
post.

~~~
imurray
One can try to catch use of gcc extensions with:

    
    
        gcc -std=c99 -pedantic

~~~
guillaumec
I usually don't use those flags because some extensions are well supported (as
long as I stay away from MSVC), and so I feel free to use them if they help
me. One example is the ##__VAR_ARGS__ gnu extension that is not strictly c99,
but not using it is just too painful for variadic macros.

~~~
kps
C11 standardizes variadic macros — see _§6.10.3 Macro replacement_
[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)

~~~
codys
Yes, even c99 has them IIRC.

The issue that was called out, however, was the use of "FOO(x, ##
__VA_ARGS__)".

GNU C has an extension that causes the ',' to be removed if __VA_ARGS__ is
empty. AFAIK, it is not standard.

------
bonn1
Out of curiosity:

Who has written C99 in the last 24h within a larger project and if yes what
kind of project?

~~~
cowsandmilk
All my code is C99. Computational chemistry program that ships on Linux, Mac,
and Windows.

~~~
throwawayaway
what do you compile with for windows?

~~~
AlexeyBrin
You can use GCC and Clang directly on Windows, both implement 100% C99.
Alternatively, Visual Studio 2013 implements most of the C99 standard (not a
complete implementation though).

~~~
throwawayaway
GCC: only as Mingw or MSYS? You can use intel too, I wanted to know what this
person was using, not what options there were.

~~~
AlexeyBrin
You don't need to install MinGW or MSYS in order to use GCC (I assume you are
interested only in C99 here and not in POSIX programming). Here is an example
of a standalone GCC (contains C, C++ and Fortran compilers):

[http://www.equation.com/servlet/equation.cmd?fa=fortran](http://www.equation.com/servlet/equation.cmd?fa=fortran)

------
matthavener
My favorite C99 trick:

    
    
        const char *lookup[] = {
          [0] = "ZERO",
          [1] = "ONE",
          [4] = "FOUR"
        };
        assert(strcmp(lookup[0], "ZERO") == 0);
    

(not available in C++ or pre-C99)

~~~
andolanra
I see this used a lot with enums to make a kind of 'homogeneous struct' where
all the members have the same type:

    
    
        enum fields = { x, y, z };
        int point[] = {
          [x] = 1,
          [y] = 2,
          [z] = 3
        };
    

This is used pretty extensively in the QEMU codebase, which is where I first
learned it.

~~~
yadyad
How does this even work?!?!

~~~
kzrdude
x, y, z being enum values, are constants.

------
randlet
Can someone explain what the purpose of the safe min macro is?

What is the advantage of this:

    
    
      #define min(a, b) ({ \
          __typeof__ (a) _a = (a); \
          __typeof__ (b) _b = (b); \
          _a < _b ? _a : _b; \
      })
    

over the naive

    
    
      #define min(a, b) (((a) < (b)) ? (a) : (b))
    
    ?

~~~
BudVVeezer
One of the two values (a or b) gets evaluated twice. Eg)

    
    
      min(a++, b++);
    

a or b would really be incremented twice.

~~~
randlet
Nice thanks. Makes perfect sense and I can see that making for a hair pulling
debug session if you weren't aware of it.

~~~
AceJohnny2
It's the kind of thing that's made me very familiar with the -E option for
GCC, which makes it spit out the preprocessed code...

------
halayli
Many of those "tricks" have nothing to do with C99.

If someone uses this switch macro in a codebase I am working on, I'll most
probably punch them in the face.

------
Zardoz84
Wow ! I Like the GL macro. I think that would be very helpfull to debug some
problems that I have on OSX related to core profile

~~~
to3m
It's very useful; I've long done the same thing. Though - you do need to do
something so you can examine the error value. Even though OpenGL's error enum
is terribly vague, most functions can produce more than one type of error.
It's nice to be able to see what the value was, even if only to verify your
assumption that what's obviously the case is indeed actually happening. Store
the value somewhere global so you can examine it in the debugger when the
program's stopped, or (if you have such a thing) use some fancier assert macro
that prints out the problem values.

Also look up GL_ARB_debug_output -
[https://www.opengl.org/registry/specs/ARB/debug_output.txt](https://www.opengl.org/registry/specs/ARB/debug_output.txt).
I don't remember this ever telling me anything terribly useful for debugging,
but I did get a couple of perf hints from it... anyway, it's vendor-specific,
so on OS X, maybe it will help.

(BTW - if you ever end up using Direct3D on Windows, be sure to activate the
debug runtime. Compare and contrast.)

~~~
someengineer
A common pattern in embedded C is to use something like "goto fail" instead of
assert, wrap your function calls in this sort of macro, and then do error
handling in one place at the end of the function.

Apparently Apple is unaware of this technique...

~~~
stephenmm
Okay, so as someone who is ramping up on C where would I go to learn all these
common patterns? I could start going through github repos and start reading
code but this seems very inefficient and I might pick up something that is
actually a bad technique.

~~~
glassx
I like Zed Shaw's Debug Macros. Actually his whole book is great.

[http://c.learncodethehardway.org/book/ex20.html](http://c.learncodethehardway.org/book/ex20.html)

------
n1mda
Any reason why they don't use trick #1 inside trick #5?

// Instead of x = x ? x : 10;

// We can use the shorter form: x = x ?: 10;

#define min(a, b) ({ \ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \ })

~~~
stingraycharles
Wouldn't that return _a < _b instead of _a?

~~~
delinka
indeed it would.

------
jokoon
Isn't there some C11 version of the language that would add those kinds of
features ? I guess they might break earlier C code though, but I'm not sure.

~~~
unwind
Yes, there is a C11 standard. See for instance
[http://en.wikipedia.org/wiki/C11_%28C_standard_revision%29](http://en.wikipedia.org/wiki/C11_%28C_standard_revision%29)
for a list of new features in C11. But no, it doesn't implement these things.

Here's a handy table showing GCC's support:
[https://gcc.gnu.org/wiki/C11Status](https://gcc.gnu.org/wiki/C11Status).

I'm pretty sure Clang supports C11 well too, didn't find a corresponding table
though. It says "By default, Clang builds C code in GNU C11 mode [...]" on
this page:
[http://clang.llvm.org/compatibility.html](http://clang.llvm.org/compatibility.html).

~~~
kps
“Clang strives to both conform to current language standards (up to C11 and
C++11)”. If anything's missing, it's a bug. clang also kindly defaults to C11
so I don't have to curse and go add a command line flag every time I write
“for (int i = ...”.

~~~
fafner
GCC 5 will default to -std=gnu11 (C11 with GNU extensions)

------
ndesaulniers
What happens if I call ARRAY_SIZE on an empty array?

~~~
dezgeg
C doesn't allow empty arrays.

~~~
ndesaulniers
How about a dangling pointer that decayed from an array?

~~~
JoachimSchipper
In that case, it'd evaluate to

    
    
        sizeof(mytype *) / sizeof(mytype)
    

which will usually be 0 or 1 (most of my arrays hold at least words.)

~~~
ndesaulniers
Sorry, I was misremembering the edge case here, which indeed is still around
pointer decay:

    
    
      #include <stdio.h>
    
      #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    
      void p (int* a) {
        printf("ARRAY_SIZE of arr = %lu, %lu, %lu\n", ARRAY_SIZE(a), sizeof(a), sizeof((a)[0]));
      }
    
      int main () {
        int arr [] = {0, 1, 2, 3, 4};
        printf("ARRAY_SIZE of arr = %lu, %lu, %lu\n", ARRAY_SIZE(arr), sizeof(arr), sizeof((arr)[0]));
        p(arr);
      }
    

prints:

ARRAY_SIZE of arr = 5, 20, 4

ARRAY_SIZE of arr = 2, 8, 4

where in the function, the arr has decayed into a pointer losing the
additional info about size (now the size of a pointer 8bytes or 64bits on my
host). Which is why you usually get the length of the array before invoking
the function and pass it in as additional information, or wrap the complete
array in a struct to preserve sizeof info
([http://spin.atomicobject.com/2014/03/25/c-single-member-
stru...](http://spin.atomicobject.com/2014/03/25/c-single-member-structs/)).

------
sold
What is the difference between x ?: y and x || y?

~~~
smorrow
|| gives 1 or 0 only?

~~~
sold
I see, thanks.

~~~
smorrow
"The C Companion" gives logical identities like

    
    
        (A && B) || (A && !B) == A,
    

but what he means by A on the RHS, I think, is that you must take into account
the fact that A_LHS might be zero. You can't really write this identity and
give a constant on the right, so he wrote the next best thing.

Well, the real next best thing would be !(!A).

------
tpush
#define ARRAY_SIZE(x) ((&(x))[1] - (x)) :-)

