C sizeof эквивалентный для макросов

Так как-s оператор возвращает размер файла в байтах, необходимо, вероятно, делать что-то как

my $size_in_mb = (-s $fh) / (1024 * 1024);

и использовать интервал () при необходимости в круглом числе. Это не похоже на размеры КБ, или МБ собирается измениться в любое время в ближайшем будущем :)

5
задан Community 23 May 2017 в 12:06
поделиться

6 ответов

Вы не можете сделать это в препроцессоре, но вам и не нужно. Просто создайте простой 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 .

17
ответ дан 18 December 2019 в 05:36
поделиться

Если вы используете autoconf или другую систему конфигурации сборки, вы можете проверить размер структур данных во время настройки и записать заголовки (например, #define SIZEOF_Entry 12 ). Конечно, это усложняется при кросс-компиляции и тому подобном, но я предполагаю, что ваша сборка и целевая архитектура одинаковы.

В противном случае да, вам не повезло.

9
ответ дан 18 December 2019 в 05:36
поделиться

Это, вероятно, не поможет, но если у вас есть возможность сделать это в 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)>(...);
1
ответ дан 18 December 2019 в 05:36
поделиться

На ум приходят два других подхода: написать небольшое приложение для написания развернутого цикла или использовать вариант устройства Даффа с ожидаемым размером структуры.

1
ответ дан 18 December 2019 в 05:36
поделиться

Вам не повезло - препроцессор даже не знает, что такое структура, не говоря уже о способах определения ее размера.

В таком случае вы могли бы просто # определите константу для того, что вы знаете размер структуры, а затем статически подтвердите, что она действительно равна размеру, используя трюк с массивом отрицательного размера.

Также вы можете попробовать просто выполнить if (sizeof (Entry) == 12) , и посмотрите, способен ли ваш компилятор оценивать условие перехода во время компиляции и удалять мертвый код. Это не такая уж большая проблема.

5
ответ дан 18 December 2019 в 05:36
поделиться

Если вам нужен минимально возможный размер для структуры (или выровнять ее по 4-байтовой границе или что-то еще), вы можете использовать упакованные или выровненные атрибуты.

В Visual В C ++ можно использовать #pragma pack , а в GCC можно использовать __attribute __ ((упаковано)) и __attribute __ ((выровнено (число-байтов)).

-1
ответ дан 18 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: