Compile time vs run time -- what is the difference?
Mike Parker
aldacron at gmail.com
Wed Dec 28 07:06:41 UTC 2022
On Wednesday, 28 December 2022 at 02:31:45 UTC, thebluepandabear
wrote:
>
> In Java and some other languages, during compile time the code
> gets executed into Java bytecode. This also happens for C#. I
> don't know if there is an equivalent 'intermediate' language
> for D that your code gets translated to.
With statically compiled languages like D, C, and C++, the
compiler ultimately translates your source code to what's
referred to as "machine code". Compilers output object files,
which are in turn linked into an executable file by a linker.
Static compilers can use intermediate representations like Java
bytecode. For example, compilation could consist of two steps
handled by two different programs, one that translates the source
to bytecode, and one that translates the bytecode to an object
file.
This is how LLVM-based compilers like Clang and LDC work. Clang
translates C source to LLVM IR (Intermediate Representation). LDC
translated C source to LLVM IR. Both pass the generated IR to the
LLVM compiler, which outputs the object files that are then given
to a linker. Static Java compilers do the same thing with Java
bytecode. Java JIT compilers built into Java VMs translate Java
bytecode to machine code while the program is running.
So compilation is just the act of translating from one source
format to another (e.g., raw source code to machine code, or raw
source code to bytecode, or bytecode to machine code).
>
> In general, I have a very vague understanding of these
> concept.s I don't understand the basics of how compile time and
> run time works in D language, it wasn't really explained in the
> book so when I see terms like 'compile time' and 'run time' I
> only have a very vague idea of what these things mean and how
> the process works for D language when compared to other high
> level languages.
>
Anything that happens at compile time means it happens while the
compiler is translating the source. Anything that happens at run
time happens while the compiled program is running.
So take this example:
```d
uint fourcc(char a, char b, char c, char d)
{
return (a << 0) | (b << 8) | (c << 16) | (d << 24);
}
// Here, fourcc is evaluated at compile time
enum nv12 = fourcc('N', 'V', '1', '2');
void main()
{
writeln(nv12);
// Here, fourcc is evaluated at runtime
writeln(fourcc('Y', 'V', '1', '2'));
}
```
When the compiler is processing this source code, it encounters
the declaration of `nv12`. Since this is an `enum`, it's a
compile-time constant that cannot be changed at run time. That
means that any value used to initialize it must also be known at
compile time. One way to do that would be to use a literal, but
in this case it's initialized with a call to the `fourcc`
function. So the compiler evaluates the fourcc function and uses
the result as the initializer of `nv12`.
In other words, the end result is just the same as if I had
written `enum nv12 = 842094158`.
The second call to `fourcc` in the main function is not in a
compile-time context, so it does not happen at compile time. It
happens at run time, i.e., when you double click the executable
that the compiler and linker generated (or type its name on the
command line).
The general rule is: if a function call is in a context such that
it *must* be evaluated at compile time, then the compiler will
evaluate it. Otherwise, it's a normal run-time evaluation.
More information about the Digitalmars-d-learn
mailing list