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