views:

424

answers:

6

I have a structure that only one function must access. The function converts tokens like "k, K, kb, KB, m, M, mb, MB, ..." into an actual unit. The purpose of this is to simplify a configuration file.

So, suppose we have:

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 ...
}

I have seen other programs where struct u2type would be declared as static (again, within a function) and I can't see how that is useful. The structure is not going to change, it will always be the same every time the function is entered. That's why I made it const.

Yet, I have seen many people do statc struct foo { ... } const foos[] = { ... }, within a function where the scope is just obvious.

Is there any benefit to doing that? I try to study ASM output prior to coming to SO with optimization questions like these, but I am not an assembly guru :)

EDIT:

Yes, I know this approach smells like feet. Some projects just have odd requirements (typically mandated by odd people). The question, however remains entirely separate from the use of the function.

+11  A: 

Making it const and making it static do two different things.

  • if it is const, each function call gets its own unchangeable instance of the struct
  • if it is static there is one changeable instance of the struct shared across all function calls

It sounds as though what you want is a struct instance that is both static and const, which is a reasonable thing to do.

Performance wise, the static version should have a slight edge, as construction of the struct instance will only be done once.

anon
What prohibits the compiler from constructing the const version only once as well?
aib
In C, I'm not sure if anything does, but it is certainly not required to.
anon
If declared `static const`, it might even get located in (or near) the code segment, and not require storage at runtime in addition to its initial value. This can matter a great deal in embedded environments with code in ROM and almost no RAM available.
RBerteig
A: 

If you declare a variable static within a function it is only initialized once when the function is entered for the first time. If you declare it non-static it is initialized each time the function is entered.

In your case it can make a slight difference. With static the array will be allocated in the static storage and initialized no more than once. Without static it will be allocated on stack and each time the function is called.

sharptooth
+5  A: 

If you declare your array static, it will be placed in the data section of the executable and initialized only once (on first access) or even not (it might be initialized in the executable already).

Without static, the data will be on the stack of each of the function's invocations, and initialized every time the function is called.

Just a little nitpick, when you say you've seen code where struct u2type is static, this is not really true. Although the static storage specifier appears before the struct, it really applies to the variable, in this case, the array. Even with

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

You can then do

struct foo foo1={ ... };

and foo1 will be an automatic variable.

jpalecek
A: 

Local variables or constants are allocated on the stack. Their existence lasts only during the function execution and their value is lost as soon as the function returns. Allocation and assignment take place each time the function is called.

Declaring a local variable or constant static means that its value will be kept from one call to the next. This is achieved by allocating it globally instead of on the stack. Allocation and assignment are performed only once, which in case of big data structures in frequently called functions may lead to performance improvments.

mouviciel
static variables are rarely if ever allocated on the heap
anon
I think "global" was meant.
Mike Dunlavey
globals are not allocated on the heap either
anon
I think mouviciel meant to say "allocated globally", rather than "allocated on the heap".
Mike Dunlavey
Thank you Mike for making my answer clear. I update accordingly.
mouviciel
A: 

Eeeww. At least change your functions name to 'case_insensitive_guess_unit'. Most of those aren't 'real' units, and those which are ('K' for example is Kelvin not kilo, 'b' is usually bit and 'B' byte) aren't the units you're returning.

If the spec is k[b] -> 1000, m[b] -> 1000000 etc, then a simple if/else is probably faster and cleaner.

Pete Kirkham
The purpose is to be forgiving in the configuration file. 'Auto' and variants are also supported, where the program chooses the smallest unit.. i.e. if user has a 120 GB disk, and 512 MB of memory, MB would be selected.
Tim Post
So what has that to do with real units? What if the user specifies data in Mb or MiB rather than MB?
Pete Kirkham
A: 

...

// 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;
}
Mike Dunlavey
That's how I would normally do it. Hence the question, hoping to squeeze every ounce out of what I must work with.
Tim Post
I think it's a key question, because it makes us distinguish between efficiency of code and efficiency of coding, not that there is a trade-off between the two. In fact, with a little code generator here, you can have both.
Mike Dunlavey