Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused about the element number is -1 for array

Tags:

c++

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;
}
like image 592
BlackMamba Avatar asked Sep 08 '16 07:09

BlackMamba


3 Answers

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); 
like image 104
sergej Avatar answered Nov 07 '22 07:11

sergej


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.

like image 26
LordWilmore Avatar answered Nov 07 '22 08:11

LordWilmore


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.

like image 1
Cheers and hth. - Alf Avatar answered Nov 07 '22 07:11

Cheers and hth. - Alf