This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Design question about global variable

Hello

Normall in an application we define global variable as:
int a;
int b;
...

How about use one structure to include all variables, and just define one structure instance? as below:
struct{ int a; int b; ...
}global;

Is the performance slower? does it take more code space? Is there any other drawback?

Thanks.

/Wang

  • But when the memory controller do not have that feature, and unaligned access generates an exception

    Yes, I saw this exception happens on iPhone's processor, I reuse a structure on iPhone and PC for socket communication, when cast a *void to *int pointer, sometimes I get exception.

    Some nice processors have intelligent memory controllers so the only cost is extra stalls because

    When unaligned, is the extra job done by compiler or CPU hardware??


    p = send_buffer;
    p += insert_32(p,a);
    p += insert_32(p,b);
    p += insert_8(p,c);

    I have lots of variable, from 20 to 50 maybe, some is char, some is int, this manual code easily make mistakes, specially when I add or remove some variables

    Now I have another idea to dump the variables for pc, no RAM is required, just define a ROM structure array, and a small function for data dump:

    1, Normally define variables, such as: int a, int b, int c

    2, Define a "smart" structure for dump only

    // Global variables
    int a;
    int b;
    int c;
    char d;
    short e;
    
    // A smart structure to describe each global variable
    typedef struct{
            void *var_ptr;
            uint8_t n_bytes;
    }var_t;
    
    // A descriptor for all global variables
    const var_t vars[]={
      {&a, sizeof(a)},
      {&b, sizeof(b)},
      {&c, sizeof(c)},
      {&d, sizeof(d)},
      {&e, sizeof(e)}
    };
    
    // Dump to a buffer, or send to UART...
    void dump(uint8_t *buf)
    {
            int i=0, j=0;
            const var_t *v=0;
            const uint8_t *p=0;
    
            for(i=0;i<sizeof(vars)/sizeof(var_t);i++){
                    v=&(vars[i]);
                    p=(uint8_t *)v->var_ptr;
                    for(j=0;j<v->n_bytes;j++){
                            *(buf++)=*(p++);
                    }
            }
    }
    

    Is this good to use?

  • I just want to know is there any drawback, or is any other better ways?

    Withing the existing structure of your program the solution you are proposing could make a lot of sense. Whether that structure is good or bad is a different matter, of course. My guess is that it can be improved.

  • "When unaligned, is the extra job done by compiler or CPU hardware??"

    When working with an architecture where the memory controller can perform unaligned accesses, then the compiler don't need to care. It generates code for one memory access, and the memory controller masks the unalign issue - all it costs is extra clock cycles. How many extra clock cycles depends on if the data is cached or if there is a need for extra fetches from RAM.

    "[...] this manual code easily make mistakes, specially when I add or remove some variables"
    Yes - but when adding/removing variables that you want to communicate through a file or to another program running on another side of a communication link, you always need to care about the details. Either by using a tagged protocol like XML, where the receiver can see which fields are sent. Or you _must_ make sure that both sides knows exactly what data you have packed.

    Letting the compiler pack the data will fail just as badly if you the other side doesn't have the exact same number of member fields in the same order and of the same size.

    But if you do need to write to a file or perform communication, then you shouldn't just make some code changes. You should have a document that descries exactly what data is sent and exactly how it is packaged. And - because of versioning issues - you should consider sending some version information so that you can catch situations when one side is newer than the other.

    "packed" is just magic that hides the complexity. And makes the developer forget that it is there. Until the very big crash/burn when the developer did something stupid, like changing the order of two members of the struct. Everything looked ok, except that the receiver unpacked something completely different.

    With explicit code for pack/unpack, a developer will know that he/she must care. And at least on the unpack side, the compiler can catch when a get_xx(p,var) is called with an incompatible variable type.

    Information hiding often sounds great. But can hurt a lot. One of the biggest problems with C++ is that code can look simple. But the reader don't get that the operators used are overloaded. And that there are magic constructors/destructors running totally invisible.

    The reason why we try to use all-uppercase for #define SYMBOL is to make sure a reader knows that there are magic "search/replace" going on and that magic could potentially be hidden, giving a totally different outcome than what the source code seems to imply.

    So "packed" may be convenient. But it's a great way to get hurt. It doesn't show that the original struct was matched against a specific file format specification of a JPEG image file. So it isn't obvious that adding a field or changing a type will suddenly break the processing of JPEG files.

    About your dump code - it shouldn't just focus on variable sizes. There is a huge difference between a 4-byte integer and an array of 4 characters. Consider byte order differences between little-endian and big-endian processors...
    Just remember that your array is basically the same as my suggested pack code - but with the important difference that my pack code was intended to pack an int32 into a generic format that isn't depending on what byte order the specific processor uses when storing the number in memory.

  • Interesting views. Person #1 states that packing reduces performance and then Person #2 suggests the use of XML.

    Why not check out my blog at http://www.kneeltronicals.com ? There's an entry about the importance of being objective.

  • Yes, but did you pick up what the view was?

    XML is a solution where all data is sent together with metadata, so that a listener can pick out exactly what data that was sent - and what wasn't sent.

    A protocol that just packs n variables binary after each other have no such metadata. Much more efficient use of the link. But with significant issues if fiels have changed offsets inside the binary package.

    So everything is a trade-off based on what the major goals was.

    When talking transfers, XML is more robust but with less efficiency than packed binary data.
    When talking about using global variables, then packed structs may be more space efficient but at the cust of code size and runtime.

    I wouldn't recommend a solution that hurt code size and access speed when running the program, just to make it a bit simpler to get a magic block of data to send to the other side. Especially when there are still lots of issues to get the other side to be able to make use of that binary blob.

  • Yes I did. Just pointing out the humour.

    Why not check out my blog at http://www.kneeltronicals.com ? There's an entry about the humour in opposite views that are both correct.

  • Why not check out my blog at http://www.kneeltronicals.com ? There's an entry about the humour in opposite views that are both correct.

    why would I ?

    wade through a ton of irrelevat stuff to find what is relevant to this issue

    BTW

    for Cortex M3 (and some others) DO NOT PACK!

    Erik

  • Erik Malund. You are as stubborn as your reputation!

    Why not check out my blog at http://www.kneeltronicals.com ? There's an entry about mules and their traits.

  • Why not check out my blog at http://www.kneeltronicals.com ? There's an entry about mules and their traits.
    because I love Google
    Google will get me to the informatin I am looking for and I do not have to wade through tons of blabber.
    nothing personal, I do not read blogs, I do not have facebook, I do not have twitter.

    if you want to dissiminate information put it where it goes do no make references to az place to search for it. If Instead of "Why not check out my blog" you could put up a link to the EXACT place where the relevant info was I would gladly look at it, but asking me to wade through a bunch of useless information will not work.

    Erik

  • No fear of that: http://www.kneeltronicals.com/ is purely fictitious - there is no content whatsoever.