2

I am trying to understand the meaning of the saying "Function calls are resolved at compiled time". I know about the concept of polymorphism and there i know that virtual functions are called(or resolve or whichever is the correct phrase i don't know the difference if any) at runtime.

I want to know what does it mean to say "compile time" or "runtime" in this(function call) context.

Below is an example and explanation of my current unerstanding which most probably is wrong.

const int n = 10; //STATEMENT 1

void func(int x)
{
    //..
}

int main()
{
   int p = 0; //this is dynamic initialization. 
 
   func(p);//STATEMENT 2 
}

To my current understanding,

  1. In statement 1, n is a constant expression and is known at compile time. So the compiler might replace all occurrences of n with 10. But it(compiler) is not required to do(replace all occurences) so. Is my explanation of this statement correct?
  2. I used to think that p is passed at runtime(whatever that means) but then i read someone say that all function calls are resolved at compile time. And i got confused. So i am not sure if this function is called/resolved at runtime or compile time. I think the reason i got confused is because

a) I don't know the fundamental difference between compile time and runtime

b) I don't know the difference between the phrase function is "resolved" and p is passed at "runtime".

So can someone clear these concepts and provide necessary links so that i can learn more about them.

  1. dynamic initialization happens at runtime and static initialization happens at compile time.
  2. compile time means hardcoded/embedded into the executable. But then when i wrote int p = 0; which is dynamic initialization and happens at runtime. But where does the integer literal 0 comes from so that it can be used to initialize the variable p at runtime. Was 0 also hardcoded into the binary and if so then why can't this statement happen(that is p can be statically initialized) at compile time.

The question might be too broad so i will appreciate(upvote) if anyone can answer any of the question.

  • 1
    Compile time means during compilation process. Runtime means when program is running. – kiner_shah Jan 03 '22 at 11:33
  • ***function calls are resolved at compile time*** maybe not compile time but link time - probably means all arguments are determined and their respective addresses are linked where the functions are called from. – kiner_shah Jan 03 '22 at 11:34
  • this might help https://en.cppreference.com/w/cpp/language/overload_resolution – 463035818_is_not_an_ai Jan 03 '22 at 11:35
  • @kiner_shah Yes i already know that compile time means during compilation and runtime means when program is running. –  Jan 03 '22 at 11:44
  • ***dynamic initialization happens at runtime*** because heap memory is available only when process is executing - runtime. – kiner_shah Jan 03 '22 at 11:45
  • @463035818_is_not_a_number I already know about overload_resolution. My confusion is that when i wrote `int p = 0;` then this happens at runtime so where did that `0` comes from at runtime. –  Jan 03 '22 at 11:45
  • `int p = 0` happens at compile time I guess. 0 is a constant. – kiner_shah Jan 03 '22 at 11:46
  • @kiner_shah NO, i think `int p = 0;` is dynamic initialization which happens at runtime. Also, i don't want people to guess. I want concrete answers. Guess work is not required. –  Jan 03 '22 at 11:47
  • 1
    Stackoverflow's [canonical list of C++ textbooks](https://stackoverflow.com/questions/388242/) provides many references to many C++ learning material that fully explain how C++ works on a fundamental level, and what any of this means. You can refer to those textbooks for explanations of how functions are called. It's not going to be useful to cut/paste entire chapters from those textbooks here, as answers to your question. Please see those textbooks for more information. – Sam Varshavchik Jan 03 '22 at 11:48
  • @AanchalSharma, what is your definition of dynamic initialization? I think that is not during runtime because that must get resolved during semantic analysis phase of the compilation process. – kiner_shah Jan 03 '22 at 11:48
  • @kiner_shah I don't have my own definition of dynamic initialization since i am not the one who is writing the C++ standard. I can only have my interpretation of dynamic initialization. That is, what i understand by dynamic initialization by reading from different sources which may or may not be correct. I refer to [this](https://en.cppreference.com/w/cpp/language/initialization) for understanding the meaning of dynamic initialization. –  Jan 03 '22 at 11:51
  • @SamVarshavchik Yes i read a lot of C++ books from the list you mentioned. And i mean from starting to end. But still i am unsure about these concepts. By unsure i mean i am not able to explain the concept to a beginner who is starting learning C++. And my thinking is that if i am not able to explain it to a beginner(*given enough time*) then i don't really understand it. –  Jan 03 '22 at 11:55
  • I really doubt that's dynamic initialization, all that gets resolved during compile time. See https://godbolt.org/z/PfYKdocjj Three tabs containing three different assemblies - first with no optimization, generates line number 12 for `int p = 0`, second with -O1 generates a slightly less optimized assembly with a MOV instruction, third with -O2 generates a better and optimized assembly with XOR instruction. This assembly couldn't be generated if it was not compile time right? – kiner_shah Jan 03 '22 at 12:09
  • The ultimate answer to your questions is to look at the assembly and see what's there. You can do that with godbolt.org. That said, I very much doubt there is no textbook in the list that makes the relevant concepts clear. – Passer By Jan 03 '22 at 12:23
  • @kiner_shah I read [here](https://stackoverflow.com/a/21932370/15545927) that **local variables are dynamically generated at runtime**. So is the above statement true only for *uninitialized* local variable? And if we explicitly initialize a local variable say like `int p = 0;` then will that local variable be not dynamically generated at runtime ? –  Jan 03 '22 at 12:30
  • Ask the author of that answer what does he mean by ***dynamically generated at runtime***, for me the statement's unclear. – kiner_shah Jan 03 '22 at 12:41
  • 1
    @kiner_shah Ok i have asked the author in the comments section of his/her [answer](https://stackoverflow.com/a/21932370/16783784). –  Jan 03 '22 at 12:47
  • @kiner_shah Another answer [here](https://stackoverflow.com/a/21932387/15545927) states that *While locals are initialized in runtime.*. This is why at the very beginning of our discussion i was saying that `int p = 0;` uses dynamic initialization. –  Jan 03 '22 at 13:03
  • At compile time the compiler determines exactly which function (name and parameters ie the signature) will be called (unless the function is virtual). The address of the called function may be fixed-up at link time (or even load time if using dynamic libraries). But this does not change the fact that the function to be called is determined at compile time. If you have 2 different functions with the same signature in your application (which the compiler may not be able to detect) the program breaks the One-Definition-Rule and has Undefined Behaviour. – Richard Critten Jan 03 '22 at 13:16
  • 1
    These days you as the programmer specify the *intention* by writing some C++ source code. The compiler turns that into a program that conforms to that intention. How it achieves that is down to it. All this talk about dynamic initialisation is not helpful when considering the end product. In your case for example, given that `main()` is not re-entrant in C++, the compiler might compile out `p` completely and pass 0 directly to `func`. It might choose to inline `func`. It might choose to compile your program to `int main(){}`. See https://en.cppreference.com/w/cpp/language/as_if. – Bathsheba Jan 03 '22 at 14:46
  • @Bathsheba It isn't helpful doesn't mean/imply that it isn't relevant. Specially in a language like `C++` where if you(we) are not careful enough, undefined behavior can occur. Also, my question is more out of curiosity than anything else. And i want to be a professional C++ developer. So understanding what is going on behind the scenes might help me in future. Also, i find your comment good so if you want you can add it as an answer and i will/can upvote it. Since in my question i have stated that people can answer the question in parts.Thanks for your last comment it was helpful to me. –  Jan 03 '22 at 15:07

2 Answers2

0

As to the main question (and question 2) about the resolution of function calls: this means that, while compiling your statement func(p);, the compiler will immediately look for a previous definition of such a function. It must find one unambiguous match, or stop compiling and complain to you. That's it!

If this resolution succeeds then yes, the call would normally occur at runtime, while executing your program. However, as mentioned, in truth you only get the deliberately loose promise that your program will behave as if this is the case.

So, to the question in point 4: no, "compile time" by itself does not necessarily imply that something will become embedded in the executable. If it does, for int p = 0; there will be an instruction to store a 0 somewhere. The value 0 comes from you, because you asked for it! Similarly, you asked for p to be a local variable, so the compiler will treat it as such. But if it can deduce that you don't actually use it, it will happily ignore it. You can see this for your own example at Compiler Explorer, where on the right is the result with optimisations enabled. You could say the value is (potentially) hardcoded, but only as part of an instruction to store it during execution.

However, while p is initialised at runtime, it's not the same as dynamic initialisation, which applies specifically to non-local variables. Even static initialisation is not actually required to happen at compile time (point 3), though it can be.

This relates back to point 1, where yes, your explanation is correct! It can be done at compile time, or as part of runtime static initialisation. You can observe in Compiler Explorer that GCC does the former: you don't see any instructions for storing n even if you use its value somewhere. In those cases, you will just see the value 10 being stored directly, as if initialised by a literal. If you initialise it with some non-constant expression, you will instead see instructions to store and retrieve that value.

Finally, unless you plan to develop compilers or other software "close to the metal", you will be fine without knowing everything the compiler does! Not that curiosity is bad, of course. But on this topic I think it's more than sufficient to know about storage duration and the "static initialisation order problem".

sigma
  • 2,758
  • 1
  • 14
  • 18
-1

first, you should know what is the meaning of Compile time resolving
Compile time resolving means the time that your code is still in compiler, and the compiler is checking and resolving all of the references within the code
For a better understanding, in this state, the code is not reading or interpreting by anyone (any runtime environment) but the compiler is assigning the blocks of ram to the variable

assume these two lines of code:

a = 1;
b = a;

in compile time, the compiler will see two initialization so it will label a block of memory "a" and put "1" into it, then it will see another initialization, it will choose another part of memory, label "b" on it, but this time it can not assign "a" to it and errors raise, why? because at compile time no one is reading a=1 so when the compiler confronts with b=a "a" is ambiguous