Perl implements its own printf formatting. But if it follows the ANSI/ISO C specification for what %#X does, it is per spec: any non-zero output is prefixed with 0x.
To always have the prifix, just mention it in the string: "0x%X".
I like your idea of using interpolation instead of join.