All the actual compiled QuakeC code is compiled into one array of instructions. There's also a bunch of indexes for things like global variables, fields and functions.
Each entry in the function list contains, among other things, the index into the instruction list of the first instruction of that function.
Builtins however have a negative index, and instead point to an index in an engine-side list of C function pointers. The engine checks the sign and if it's negative it looks in the builtin list and calls the C function rather than interpreting any instructions from the progs. The # number in the declaration/definition of a builtin is its actual position in the builtins list.
So the engine has to define every single builtin function that gets made available to the QC. They're generally for something that QC can't do on its own, or which would be much slower to do in QC. To QC they behave exactly like QC functions - they take parameters, they return a value and they can affect other globals or entities while running.
I don't know if that fully explains it. I have further but they're incomplete and aimed for developing a QC interpreter. There's also , which I used when making those notes.
(While posting this I noticed slight errors in my notes, but they still demonstrate the general structure of a compiled progs.dat)