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

Parents
  • "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.

Reply
  • "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.

Children