Because a pointer to empty would be quite stupid. While you can technically build an allocated array with a capacity of zero with some hacking the RTL always cleans up the memory as soon as an arrays length becomes 0.
Fun fact - checking against nil for the purpose of "is it empty or not" opposed to comparing Length to 0 is slightly faster:
procedure test(const a: TBytes);
begin
if a <> nil then
Writeln;
if Length(a) > 0 then
Writeln;
end;
CheckArray.dpr.12: begin
0041D57C 53 push ebx
0041D57D 8BD8 mov ebx,eax
CheckArray.dpr.13: if a <> nil then
0041D57F 85DB test ebx,ebx
0041D581 740F jz $0041d592
CheckArray.dpr.14: Writeln;
0041D583 A1B4254200 mov eax,[$004225b4]
0041D588 E8CF7DFEFF call @WriteLn
0041D58D E8B270FEFF call @_IOTest
CheckArray.dpr.15: if Length(a) > 0 then
0041D592 8BC3 mov eax,ebx
0041D594 85C0 test eax,eax
0041D596 7405 jz $0041d59d
0041D598 83E804 sub eax,$04
0041D59B 8B00 mov eax,[eax]
0041D59D 85C0 test eax,eax
0041D59F 7E0F jle $0041d5b0
CheckArray.dpr.16: Writeln;
0041D5A1 A1B4254200 mov eax,[$004225b4]
0041D5A6 E8B17DFEFF call @WriteLn
0041D5AB E89470FEFF call @_IOTest
CheckArray.dpr.17: end;
0041D5B0 5B pop ebx
0041D5B1 C3 ret