Я читаю код отсюда: https://github.com/chenshuo/muduo/blob/ master / muduo / base / Date.cc

Но меня смущают эти две строки:

char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];

А также

(void) require_32_bit_integer_at_least; // no warning please

Какая у них цель?

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;
}
c++
8
BlackMamba 8 Сен 2016 в 10:43

3 ответа

Лучший ответ

Код требует, чтобы int был как минимум 32-битным. Если это не так и sizeof(int) меньше 32 бит, вы получите сообщение об ошибке:

error: size of array 'require_32_bit_integer_at_least' is negative

Линия

(void) require_32_bit_integer_at_least; // no warning please

Похоже, чтобы избежать предупреждения о "неиспользованной переменной". Однако, поскольку массив является глобальным и нестатическим, компилятор все равно не выдаст предупреждение. Знание того, что глобальная нестатическая переменная действительно не используется, потребует проверки всех единиц перевода (исходных файлов) во всем проекте.


По предложению @MartinBonner, чтобы сделать его более понятным и простым в использовании, мы могли бы определить макрос «static assert»:

#define STATIC_ASSERT(EXPR, MSG) typedef char static_assertion_##MSG[(EXPR) ? 1 : -1]

И используйте его следующим образом:

STATIC_ASSERT(sizeof(int) >= sizeof(int32_t), int_is_less_than_32_bit);    

const bool foo = true;
STATIC_ASSERT(foo, foo_is_not_true); 
7
sergej 9 Сен 2016 в 18:20

char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1]; объявляет массив до того, как будет запущен какой-либо фактический код внутри ваших методов. Если размер int меньше 32 бит (например, компилятор, где int равен 24 или 16 битам), то он попытается создать массив размером -1, что недопустимо и вызовет ошибку, означающую, что код не запускается.

Строка (void) require_32_bit_integer_at_least; // no warning please не дает компилятору жаловаться на неиспользуемый массив.

1
LordWilmore 8 Сен 2016 в 10:47

В C ++ 11 и новее просто используйте стандартный static_assert .

Вы смотрите на одну конкретную технику C ++ 03 для реализации статического (то есть времени компиляции) утверждения.

Альтернативный метод использовал typedef типа, вложенного в шаблон класса, который не имел такого вложенного типа для аргумента шаблона false. Это имело преимущество в том, что typedef может встречаться где угодно и может повторяться с идентичным определением (если только компилятор не соответствует требованиям, как это было в то время). Методика может быть доработана, чтобы обеспечить достойное информативное сообщение об ошибке, которое Андрей Александреску исследовал в своей уже ставшей классической книге «Современный дизайн C ++».


Так как же

char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];

… Работать как статичное утверждение?

Хорошо, если размер массива равен -1, значит, код неправильно сформирован.

Он также будет неправильно сформирован с размером массива 0, но некоторые компиляторы ошибочно примут это; следовательно, условный оператор (или в некоторых случаях арифметическое выражение) вместо простого логического.


С утверждением в локальной области следующие

(void) require_32_bit_integer_at_least; // no warning please

… Будет делать именно то, что объясняет комментарий: там он подавляет возможное предупреждение о том, что переменная не используется.

Однако в исходном коде утверждение находится в области пространства имен, а приведение к void находится внутри функции. Это бессмысленно для стандартного C ++. Одна из возможных причин может заключаться в том, что конкретный компилятор оптимизировал переменную утверждения и ошибочно принял код, в котором это утверждение не выполнялось, и что локальное использование переменной предотвратило такое поведение, при этом комментарий полностью вводил в заблуждение.

1
Cheers and hth. - Alf 9 Сен 2016 в 08:29