The memory usage of a program is not a function of the language in which that program is written. You can write code that uses a ton of memory in C#, you can do the same in C.
That said, I will try to address some of what you're asking:
how are stored and handled global variables
They are given memory addresses. When you use a global, the compiler just uses that known address. (What, did you expect a complex answer?)
that global variables are locate at the end of the program code
On some architectures that may be the case, but it need not be. On Windows (using the Portable Executable file format) they are not in any way related, and may be mapped to completely different arbitrary locations. In fact, most likely this is not the case on more recent architectures, which discourage placing code where data lives (for security purposes -- you don't want a buffer overrun to be allowed to overwrite your program code)
if I am not wrong, on modern x86 OSes, every program gets its own adress space starting from 0
You are not wrong in theory, but you are wrong in fact. Even if linkers could really do this, few would, simply because 0 is used as the null
constant. Usually however, the issue is that there are dynamic libraries, or other items that consume pieces of your process' address space, well before your code is actually loaded. (For example, a reference to the file where your code is located, or a block of memory which contains the command line passed to your program)
I read that allocating memory using malloc expands heap
Well, you're assuming that there is only one heap. On Windows at least, each DLL usually has it's own heap, and you can create heaps on the fly/at will. The way heaps are classically explained in Computer Science courses are usually assuming a system where there is no base operating system or virtual memory in play.
You are confusing memory with address space here for modern processors. Address locations of things often have very little to do with where they are physically stored. The Wikipedia article on Virtual Memory might make things make a bit more sense for you. Good luck!
EDIT:
the PE exe file actually has informations about global variables that can be distinguished from other data
Not exactly. The PE file format has a section where static data is stored, and that region of the file is memory mapped. The code knows where in that big chunk where the specific globals you're looking for are.
That Os actualy maps them to lets say "best" space available
Modern processors use a flat memory model. It's just as easy to access any one address as it is to access any other.
I always thought that compiled code is no further changed by OS at runtime
It isn't (well, for the most part, the reasons it might change are a whole can of worms in and of themselves). To access the global, the code itself needs to know the base address at which it is loaded. It can calculate where the data block of the PE file is loaded from that, for the most part. That said, compilers are free to put globals pretty much anywhere; the fact that the PE spec has a place for initialized data does not mean the compiler has to use it (MingGW, for example, I believe does not use that area).
First, does .exe contains information about stack size needed?
Yes, there are settings controlling both the reserved size of the stack as well as the committed size of the stack. Because Stack Overflows can be handled safely on Windows, usually the stack is only 1 MB; on *nix machines it's usually 8MB or more.
And is stack size limited?
Not as far as I am aware. That said; there are of course practical limitations. First and foremost, address space reserved for the stack will not be usable for anything other than the stack. There are also large portions of the address space that are reserved by the Kernel for various uses; not to mention the actual code and data on which your program operates. If you are using more than 1MB of stack, you should consider using a heap allocated stack for your data, and switch to an iterative solution, or seriously rethink how your program operates. 1MB of stack is much much more than is commonly used.
And second, is there any article you now about, that contains this informations, and/or informations what does PE format contauns are how is this coded to be seen when disassembling .exe file
You can read the PE Spec: http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx
On modern systems, you can essentially forget about knowing exactly where code segments and data are located both physically and virtually. The Processor does not care or enforce anything like this, so there is no reason any operating system or program is forced to use any sort of memory organization. In particular, the concept of a Heap in Windows is much different than what is typically taught in Computer Science courses. In Windows (and other modern OSs), the heap is nothing more than a bunch of memory dolled out by the OS. The location, however, of that memory is completely variable. Ask for the OS for one block, you might get it at 0x00005556, and you might get the next block at 0xFFFF890. There's no reason for a distinction because the processor underneath simply does not care.