-2

On stack overflow I ran into a question What is ":-!!" in C code?

> #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
> #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))

out of curiosity I want to know how can I use these kind of macros ?

int main()
{
    BUILD_BUG_ON_ZERO(0);
    return 0;
}

In the above code it gives an error that type name is not allowed.

EDIT : the code compiles on linux using gcc but fails on visual studio

Community
  • 1
  • 1
theadnangondal
  • 1,546
  • 3
  • 14
  • 28

1 Answers1

4

Read the best answer carefully:

The macro is somewhat misnamed; it should be something more like BUILD_BUG_OR_ZERO, rather than ...ON_ZERO

So it fails to compile when the parameter is nonzero:

int main()
{
    BUILD_BUG_ON_ZERO(1);
    return 0;
}

http://ideone.com/TI97r3


As for a practical usage:

int main()
{
    BUILD_BUG_ON_ZERO(sizeof(int) != 4); // we need int to be 4 bytes, stop compilation otherwise
    return 0;
}

As for C++: this is a C construct that does not compile in C++ at all.

In C++11 you can use a static_assert instead.

Community
  • 1
  • 1
Csq
  • 5,775
  • 6
  • 26
  • 39
  • 2
    Of course, in C++, you could redefine the macro to a suitable `static_assert`. – Angew is no longer proud of SO Sep 22 '14 at 11:38
  • 1
    I think _UNLESS_ZERO would be even better than _OR_ZERO – Tom Tanner Sep 22 '14 at 11:49
  • 2
    just for the records `static_assert` is common between C++11 and C11. – Jens Gustedt Sep 22 '14 at 15:23
  • 1
    `static_assert` isn't as flexible and can't always be used as a substitute. `BUILD_BUG_ON_ZERO` also returns an expression (`(size_t)0`), so it can be used in many (tricky, but highly useful) macro definitions, as well as just as a statement. See, for example, the `ARRAY_SIZE` and `__must_be_array` macros in `include/linux/kernel.h`. – Craig Barnes Apr 10 '18 at 22:03