Я читаю код отсюда: 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;
}
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);
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
не дает компилятору жаловаться на неиспользуемый массив.
В 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 ++. Одна из возможных причин может заключаться в том, что конкретный компилятор оптимизировал переменную утверждения и ошибочно принял код, в котором это утверждение не выполнялось, и что локальное использование переменной предотвратило такое поведение, при этом комментарий полностью вводил в заблуждение.
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.