I'm reading a code from here: https://github.com/chenshuo/muduo/blob/master/muduo/base/Date.cc
But I'm confused about these two lines:
char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];
and
(void) require_32_bit_integer_at_least; // no warning please
What's the purpose of them?
char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];
int getJulianDayNumber(int year, int month, int day)
{
(void) require_32_bit_integer_at_least; // no warning please
int a = (14 - month) / 12;
int y = year + 4800 - a;
int m = month + 12 * a - 3;
return day + (153*m + 2) / 5 + y*365 + y/4 - y/100 + y/400 - 32045;
}
The code requires that an int
is at least 32 bit wide.
If that is not the case and sizeof(int)
is less than 32 bit you would get an error like:
error: size of array 'require_32_bit_integer_at_least' is negative
The line
(void) require_32_bit_integer_at_least; // no warning please
seems to be to avoid the "unused variable" warning. However, as the array is global and non-static the compiler would not generate a warning anyhow. Knowing that a global non-static variable is really unused would require checking all translation units (source files) in the entire project.
As proposed by @MartinBonner, to make it clearer and easier to use, we could define a "static assert" macro:
#define STATIC_ASSERT(EXPR, MSG) typedef char static_assertion_##MSG[(EXPR) ? 1 : -1]
and use it as follows:
STATIC_ASSERT(sizeof(int) >= sizeof(int32_t), int_is_less_than_32_bit);
const bool foo = true;
STATIC_ASSERT(foo, foo_is_not_true);
char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];
is declaring an array before any actual code inside your methods is run. If the size of an int is less than 32 bit (e.g. a compiler where an int is 24 or 16 bits), then it will attempt to create an array of size -1, which is not allowed and will cause an error meaning that the code will not run.
The line (void) require_32_bit_integer_at_least; // no warning please
stops the compiler from complaining about an unused array.
In C++11 and later just use standard static_assert
.
You're looking at one particular C++03 technique to implement a static (that is, compile time) assertion.
An alternative technique used a typedef
of a type nested in a class template, which did not have such a nested type for false
template argument. This had an advantage in that a typedef
can occur just about anywhere, and can be repeated with identical definition (unless the compiler is non-conforming, as one was at the time). The technique could be further elaborated to provide a decent informative error message, which Andrei Alexandrescu explored in his now classic “Modern C++ Design” book.
So how does
char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];
… work as a static assertion?
Well if the array size is -1
then the code is ill-formed.
It would also be ill-formed with array size 0
, but some compilers would erroneously accept that; hence the conditional operator (or in some cases an arithmetic expression) instead of a simple boolean.
With the assert in a local scope, the following
(void) require_32_bit_integer_at_least; // no warning please
… would do exactly what the comment explains: there it suppresses a possible warning about the variable not being used.
However, in the original code the assert is at namespace scope and the cast to void
inside a function. That's meaningless for standard C++. One possible reason could be that a specific compiler optimized away the assertion variable, and erroneously accepted code where that assertion did not hold, and that the local use of the variable prevented that behavior, with the comment then completely misleading.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With