One other way to observe these steps a bit more clearly is to look at the startup code provided by a chip's manufacturer or generated by an IDE that targets the chip, such as Keil. Most will put this type of code in '.S' startup assembly files, which often also contain information like the memory addresses for hardware interrupts to use, and linker scripts for telling the compiler about the memory available on the ch…
It's not just "good practice", but instead the startup code is so specific to the platform that there really isn't "generic" startup code.
What happens before main() is executed in C and why is it important?
31–40 of 104 posts
Re: What happens before main() is executed in C and why is it important?
#32Re: What happens before main() is executed in C and why is it important?
#33The linker script is what runs the global constructors in C++. Nothing preventing using a custom linker script in C to call some `premain()` function.
Re: What happens before main() is executed in C and why is it important?
#34Earlier quoted context omitted.
It's not just "good practice", but instead the startup code is so specific to the platform that there really isn't "generic" startup code.
The generic compiler-provided startup code is fine for AVRs under most circumstances, since they're only produced by a single manufacturer and don't have fancy features like PLLs which need to be initialized. It's the more complicated chips where it gets a little hairy, especially if you have to deal with things like external RAM.
Re: What happens before main() is executed in C and why is it important?
#35Seriously-- why is the font greyed out? What possible purpose does this serve?
Re: What happens before main() is executed in C and why is it important?
#36Earlier quoted context omitted.
In embedded you can usually modify every step from boot to main. They are just pieces of code you can interact with and make them do whatever you want and initialize stuff in whatever order you want, providing you know what you do. Deviating with a war story now, I once modified some startup code so it self-detected its boot location and initialized the ram data according to this location shift. It was fun, but debug…
What was the project for where you wrote code that self-detected its boot location?
I also wanted to maintain full functionality even at shifted location in case the self-copy process somehow failed. Never did fail, at least to my knowledge.
Re: What happens before main() is executed in C and why is it important?
#37It should be noted that relying on static initialization as suggested in the article, while at times useful, can open a new set of problems until initialization order is well-defined (it's out of scope for the article, so I imagine the author is aware and just opting for brevity). Some compilers provide an explicit ordering mechanism (clang and GCC) and the there are proposals in the C++ standards at the moment, but…
Is atexit the post-main hook to which you were referring, or is that just the posix hook into a larger class of post-main hooks?
Re: What happens before main() is executed in C and why is it important?
#38Earlier quoted context omitted.
Can you elaborate for those of us unfamiliar with topic?
Doing some of that kind of super low level code in a C++ static initialization constructor is almost certainly a poor choice. Like setting up memory and the stack pointer. Doing hardware init there can make a lot of sense, but you have to be careful from an architectural perspective.
Re: What happens before main() is executed in C and why is it important?
#39Did someone on HN downvote everything except the bullet points in this article? Seriously-- why is the font greyed out? What possible purpose does this serve?
p{color:#999;line-height:1.4;margin-bottom:.75em}
so paragraph tags, sadly, have the ugly grey font color by default
Re: What happens before main() is executed in C and why is it important?
#40Earlier quoted context omitted.
Doing some of that kind of super low level code in a C++ static initialization constructor is almost certainly a poor choice. Like setting up memory and the stack pointer. Doing hardware init there can make a lot of sense, but you have to be careful from an architectural perspective.
The article is not advocating initializing the stack pointer with a C++ constructor.
> * Command line arguments are received. This may not be relevant in embedded systems as in embedded systems we don’t usually call main() with arguments
> * The stack pointer is configured. This is necessary because the program needs to know where to start from. Note that some microcontrollers may require a start.c or cstart file that has the initialization code (whether this file is manually created or auto generated).
> Now that we know what happens before main(), we might wonder if there’s a way we can control what happens before main, or if there is a way we can write our own version of what happens before main(). In C, the answer is largely no. Whatever happens before main() is largely dependent on your architecture and compiler. However this is in fact possible in C++.
> One way you can do this in C++ is by declaring a global class object. Since global variables are initialized before main(), the constructor of the class you have initialized as global will run before main(). You can therefore place the code you want to run before main() in such a constructor.
Certainly looks like it is.