Thread: How are structs initalized to zero?

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    51

    How are structs initalized to zero?

    I have a struct declaration in a header file:

    Code:
    // myheader.h:
    
    struct testStruct
    {
        char myChar;
        int myInt;
        char array[200];
    } myStruct;
    In my C file I have the include for my header:

    Code:
    #include "myheader.h"
    
    int main()
    {
    
       extern testStruct myStruct;
       .....
       return 0;
    }
    Anyway, I noticed that the values in my struct were all initialized to zero already. Is this just something my compiler decided to do? Should I go about initializing all the values to zero before I start using the struct, or is this part of the C89 standard or something?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Global variables are ALWAYS initialized to zero by the compiler [unless you initialize it differently in your source-code], in the sense that they are stored in a region that will be filled with zeros. If you add your own initialization, e.g.
    Code:
    // myheader.h:
    
    struct testStruct
    {
        char myChar;
        int myInt;
        char array[200];
    } myStruct = { 17, 3400, "John Smith" };
    then by most likelyhood it will also move to "initialized data", so where the compile fills it with the relevant data.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    That's one thing I've never quite understood. Why are global variables initialized to 0, but not normal variables? If C doesn't initialize to make code faster, why not leave globals uninitialized also?
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cpjust View Post
    That's one thing I've never quite understood. Why are global variables initialized to 0, but not normal variables? If C doesn't initialize to make code faster, why not leave globals uninitialized also?
    Because it's a one-time initialization - local variables are created and destroyed every time the function is called. So the compiler lets you do the work when and as you need it, rather than filling everything with zero, and then you initialize it with something else anyways. If you have Visual Studio, you can compare the time it takes in a debug build with a release build. Sure there are other things - so do a release build with the lowest level of optimization, and compare that. You will probably find that there is a factor 3-4 in performance difference. Most of that is because Visual Studio's debug runtime fills local variables with 0xCC - which takes a lot of extra time.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    But couldn't the app start faster if it didn't initialize global variables? You'd think they'd take all the speed optimizations they can get...
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cpjust View Post
    But couldn't the app start faster if it didn't initialize global variables? You'd think they'd take all the speed optimizations they can get...
    Filling 1MB of RAM with zeros takes about 40ns * 1024 * 1024 / 16 seconds - that is about 2.5 milliseconds (that is the time to actually write it to memory, not the time it takes to write it to the cache - that is faster). I don't think you care if your application startup time is 2.5ms faster or not. It will take about 4 times longer if your hard-disk is just a little fragmented and the hard-disk head has to seek to another track to get one block of the executable file loaded.

    And it happens ONCE at startup (and one MB of data is quite a bit)

    Finally, if you don't fill it with zero's, it needs filling with something else, since we do not want an applicaiton starting to be able to find our credit card number, love-letters to secret lover, or whatever else may have been left around in the memory from another application that just exited. So the memory needs to be filled with something - it doesn't take more or less time to fill it with zero compared to filling it with random gunk or something else that has some sort of meaning. Zero does make more sense than random gunk, since it allows some sort of predictability, and we don't need to fill our data with zero in the code itself.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    That brings me to a possibly useful tip. You can avoid the time spent 0xCC filling stack variables by using constructor initialisation lists rather than assignment, and of course using construction instead of assigment in the calling code.
    I find this helps debug build code run closer to the speed of release build code.
    It's essentialy bypassing the uninitialised state of a variable by giving it a value as it comes into existence, instead of after.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Unfortunately C doesn't have constructors, and if you have to declare variables at the top of the scope you don't always have anything to initialize them with.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    That brings me to a possibly useful tip. You can avoid the time spent 0xCC filling stack variables by using constructor initialisation lists rather than assignment, and of course using construction instead of assigment in the calling code.
    I find this helps debug build code run closer to the speed of release build code.
    It's essentialy bypassing the uninitialised state of a variable by giving it a value as it comes into existence, instead of after.
    That's probably something you should do anyway. If this were C++. (But we're in the C forum, so it probably isn't.)

    It's a little surprising to me that the compiler doesn't optimize assignments in constructors into initialization. I guess we're talking about debug mode here, though.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by dwks View Post
    It's a little surprising to me that the compiler doesn't optimize assignments in constructors into initialization. I guess we're talking about debug mode here, though.
    Indeed - and it's not so much about "doesn't optimize", but rather that you may want to improve the chances of finding that nasty bug caused by not initializing member variable blah in your constructor, which once every 4 weeks causes the applicaton to crash randomly, because at that particular point, it doesn't do the same thing that it usually does, and so on and so forth.

    I'm a tiny bit surprised it actually helps in any way in debug mode, because I think the way it works is that the compiler fills all the local stack space with 0xCC (or similar), when it enters the function - so as long as the stack-space is being used up, it will be filled with 0xCC at all times - no matter how/where the constructions/initialization is done - I could be wrong, I haven't looked at the code. I have found it very useful to find certain kinds of errors, including in our rather large production code at work.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by matsp View Post
    Filling 1MB of RAM with zeros takes about 40ns * 1024 * 1024 / 16 seconds - that is about 2.5 milliseconds (that is the time to actually write it to memory, not the time it takes to write it to the cache - that is faster). I don't think you care if your application startup time is 2.5ms faster or not. It will take about 4 times longer if your hard-disk is just a little fragmented and the hard-disk head has to seek to another track to get one block of the executable file loaded.

    And it happens ONCE at startup (and one MB of data is quite a bit)

    Finally, if you don't fill it with zero's, it needs filling with something else, since we do not want an applicaiton starting to be able to find our credit card number, love-letters to secret lover, or whatever else may have been left around in the memory from another application that just exited. So the memory needs to be filled with something - it doesn't take more or less time to fill it with zero compared to filling it with random gunk or something else that has some sort of meaning. Zero does make more sense than random gunk, since it allows some sort of predictability, and we don't need to fill our data with zero in the code itself.

    --
    Mats
    I'm not saying it's a bad thing that it zero initializes global variables; it's just surprising, since C is built for performance in every other way.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cpjust View Post
    I'm not saying it's a bad thing that it zero initializes global variables; it's just surprising, since C is built for performance in every other way.
    Yes, but it's also about usability - and in MANY cases, the data would have to zero initialized anyways. The difference with local variables is mostly that the memory they use is recycled from previous function calls [most of the time], and that is what causes the overhead when it needs to be done EVERY function call - and by the way, C is by no means unique in this aspect - nearly all Algol-related languages have "undefined content of local variables" - it's for speed reasons, but it's much more because you have to fill the functions local variables EVERY time the function is called.

    Filling global variables once is very small overhead. Filling local variables each time the function is called is a significant overhead.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Creating array of structs
    By knirirr in forum C++ Programming
    Replies: 12
    Last Post: 06-18-2008, 08:30 AM
  2. Multidimentional structs + memcpy() == FAIL
    By Viper187 in forum C Programming
    Replies: 8
    Last Post: 06-18-2008, 02:46 AM
  3. packed structs
    By moi in forum C Programming
    Replies: 4
    Last Post: 08-20-2002, 01:46 PM
  4. ArrayLists + Inner Structs
    By ginoitalo in forum C# Programming
    Replies: 5
    Last Post: 05-09-2002, 05:09 AM
  5. Searching structs...
    By Sebastiani in forum C Programming
    Replies: 1
    Last Post: 08-25-2001, 12:38 PM