2009-03-25 2 views
4

У меня есть структура, к которой должен иметь доступ только одна функция. Функция преобразует токены, такие как «k, K, kb, KB, m, M, mb, MB, ...» в фактическую единицу. Целью этого является упрощение файла конфигурации.Объявление структур внутри функций в C

Итак, предположим, что мы имеем:

static uint32_t real_unit(const char *str) 
{ 
    struct u2type { 
     char key[3]; 
     uint32_t val; 
    } const u2types[] = { 
     { "k", KB_UNIT }, 
     { "K", KB_UNIT }, 
     { "kb", KB_UNIT }, 
     { "KB", KB_UNIT }, 
     { "m", MB_UNIT }, 
     { "M", MB_UNIT }, 
     { "mb", MB_UNIT }, 
     { "MB", MB_UNIT }, 
     { "g", GB_UNIT }, 
     { "G", GB_UNIT }, 
     { "gb", GB_UNIT }, 
     { "GB", GB_UNIT }, 
     { { 0 }, 0 } 
    }; 

    ... code to look up str ... 
} 

Я видел других программ, где структура u2type будут объявлены как статические (опять же, в функции), и я не могу видеть, как это полезно. Структура не изменится, она всегда будет одинаковой при каждом вводе функции. Вот почему я сделал это const.

Тем не менее, я видел, что многие люди делают statc struct foo {...} const foos [] = {...}, в пределах функции, где область видимости очевидна.

Есть ли какая-либо польза для этого? Я пытаюсь изучить вывод ASM до прихода к SO с оптимизации подобные вопросы, но я не собрание гуру :)

EDIT:

Да, я знаю, что этот подход пахнет ноги. Некоторые проекты имеют странные требования (как правило, нечетные люди). Однако вопрос остается полностью отделенным от использования функции.

ответ

13

Составляя его const и делая его статическим, делайте две разные вещи.

  • если это сопзЬ, каждый вызов функции получает свой собственный неизменяемый экземпляр структуры
  • если она статична есть один изменчивый экземпляр структуры используется во всех вызовы функций

Это звучит как будто вы хотите, это экземпляр struct, который является как static, так и const, что разумно.

Производительность, статическая версия должна иметь небольшое преимущество, так как построение экземпляра struct будет выполняться только один раз.

+0

Что запрещает компилятор построения константных версий только один раз, а? – aib

+0

В C я не уверен, что что-то делает, но это, безусловно, не требуется. – 2009-03-25 15:24:42

+0

Если объявлен 'static const', он может даже попасть в (или рядом) сегмент кода и не требовать хранения во время выполнения в дополнение к его начальному значению. Это может иметь большое значение во встроенных средах с кодом в ПЗУ и почти без ОЗУ. – RBerteig

0

Если вы объявляете переменную static внутри функции, она инициализируется только один раз, когда функция вводится в первый раз. Если вы объявляете его нестатичным, он инициализируется каждый раз, когда вводится функция.

В вашем случае это может иметь небольшое значение. С static массив будет выделен в статическом хранилище и инициализирован не более одного раза. Без static он будет выделен на стек и каждый раз, когда вызывается функция.

5

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

Без статических данных данные будут находиться в стеке каждой из функций вызова и инициализируются каждый раз при вызове функции.

Немного nitpick, когда вы говорите, что видели код, где struct u2type является статическим, это не так. Хотя спецификатор статического хранилища появляется перед структурой, он действительно применяется к переменной, в данном случае массиву.Даже с

static struct foo { ... } foos [] = { ... }; 

Вы можете сделать

struct foo foo1={ ... }; 

и foo1 будет автоматическая переменная.

0

Локальные переменные или константы выделяются в стеке. Их существование длится только во время выполнения функции, и их значение теряется, как только функция возвращается. Распределение и присвоение выполняются каждый раз при вызове функции.

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

+0

Статические переменные редко бывают когда-либо выделены на кучу – 2009-03-25 11:10:30

+0

Я думаю, что подразумевалось «глобальное». –

+0

Глобалы не выделены на кучу. – 2009-03-25 14:07:54

0

Eeeww. По крайней мере, измените имя своей функции на «case_insensitive_guess_unit». Большинство из них не являются «реальными» единицами, а те, которые («K», например, являются Kelvin, а не кило, «b» обычно бит и «B») не являются единицами, которые вы возвращаете.

Если спецификация k [b] -> 1000, m [b] -> 1000000 и т. Д., То простой if/else, вероятно, быстрее и чище.

+0

Цель заключается в том, чтобы прощать в файле конфигурации. Также поддерживаются опции «Авто» и варианты, где программа выбирает самый маленький блок. Например, если пользователь имеет диск емкостью 120 ГБ и 512 МБ памяти, будет выбран MB. –

+1

Итак, что это значит с реальными единицами? Что делать, если пользователь указывает данные в Mb или MiB, а не в MB? –

0

...

// so, do you want odor-free, or fast ? 
switch (str[0]){ 
case 'g': case 'G': 
    return GB_UNIT; 
case 'k': case 'K': 
    return KB_UNIT; 
case 'm': case 'M': 
    return MB_UNIT; 
} 
+0

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

+0

Я думаю, что это ключевой вопрос, потому что он заставляет нас различать эффективность кода и эффективность кодирования, а не то, что между ними есть компромисс. На самом деле, с небольшим генератором кода, вы можете иметь оба. –

Смежные вопросы