Так как-s оператор возвращает размер файла в байтах, необходимо, вероятно, делать что-то как
my $size_in_mb = (-s $fh) / (1024 * 1024);
и использовать интервал () при необходимости в круглом числе. Это не похоже на размеры КБ, или МБ собирается измениться в любое время в ближайшем будущем :)
Вы не можете сделать это в препроцессоре, но вам и не нужно. Просто создайте простой if
в вашем макросе:
#define PROCESS_ENTRY(i) bytes[i] ^= 1; /*...etc, etc, */
if (sizeof(Entry) == 12) {
PROCESS_ENTRY( 0);PROCESS_ENTRY( 1);PROCESS_ENTRY( 2);
PROCESS_ENTRY( 3);PROCESS_ENTRY( 4);PROCESS_ENTRY( 5);
PROCESS_ENTRY( 6);PROCESS_ENTRY( 7);PROCESS_ENTRY( 8);
PROCESS_ENTRY( 9);PROCESS_ENTRY(10);PROCESS_ENTRY(11);
} else {
size_t i;
for (i = 0; i < sizeof(Entry); i++) {
PROCESS_ENTRY(i);
}
}
sizeof
- это постоянное выражение, и сравнение константы с константой также является константой. Любой здравомыслящий компилятор C оптимизирует ветвь, которая всегда ложна во время компиляции - сворачивание констант - одна из самых основных оптимизаций. Однако вы теряете #warning
.
Если вы используете autoconf или другую систему конфигурации сборки, вы можете проверить размер структур данных во время настройки и записать заголовки (например, #define SIZEOF_Entry 12
). Конечно, это усложняется при кросс-компиляции и тому подобном, но я предполагаю, что ваша сборка и целевая архитектура одинаковы.
В противном случае да, вам не повезло.
Это, вероятно, не поможет, но если у вас есть возможность сделать это в C ++, вы можете использовать шаблон, чтобы компилятор отправлял в соответствующий цикл во время компиляции:
template <std::size_t SizeOfEntry>
void process_entry_loop(...)
{
// ... the nonoptimized version of the loop
}
template <>
void process_entry_loop<12>(...)
{
// ... the optimized version of the loop
}
// ...
process_entry_loop<sizeof(Entry)>(...);
На ум приходят два других подхода: написать небольшое приложение для написания развернутого цикла или использовать вариант устройства Даффа с ожидаемым размером структуры.
Вам не повезло - препроцессор даже не знает, что такое структура, не говоря уже о способах определения ее размера.
В таком случае вы могли бы просто # определите константу для того, что вы знаете размер структуры, а затем статически подтвердите, что она действительно равна размеру, используя трюк с массивом отрицательного размера.
Также вы можете попробовать просто выполнить if (sizeof (Entry) == 12)
, и посмотрите, способен ли ваш компилятор оценивать условие перехода во время компиляции и удалять мертвый код. Это не такая уж большая проблема.
Если вам нужен минимально возможный размер для структуры (или выровнять ее по 4-байтовой границе или что-то еще), вы можете использовать упакованные или выровненные атрибуты.
В Visual В C ++ можно использовать #pragma pack , а в GCC можно использовать __attribute __ ((упаковано)) и __attribute __ ((выровнено (число-байтов)).