SCALARs and strings · Numeric functions

hex#

Interpret a string as a hexadecimal numeral and return its numeric value.

hex reads EXPR as a sequence of hex digits — optionally introduced by a 0x or x prefix — and returns the integer those digits represent. If EXPR is omitted, $_ is used. The companion operation, turning a number back into a hex string, is sprintf with the "%x" or "%X" format.

Synopsis#

hex EXPR
hex                 # operates on $_

What you get back#

A non-negative number. hex itself never returns a negative value: it has no notion of sign, it only decodes digits.

  • If the result fits in a native integer (typically 64-bit unsigned on a 64-bit build), you get an integer.

  • If the decoded value exceeds that range, hex falls back to an IEEE 754 double. A warning is emitted under use warnings and precision may be lost for values above 2**53.

To convert the other direction:

sprintf "%x", 255            # "ff"
sprintf "0x%08X", 4096       # "0x00001000"

Examples#

Plain hex digits, with or without the 0x prefix:

print hex '0xff';            # 255
print hex 'ff';              # 255
print hex 'DEADBEEF';        # 3735928559

Underscores between digits are permitted as visual separators, the same way numeric literals allow them:

print hex '1_0000';          # 65536
print hex 'cafe_f00d';       # 3405700109

Operating on $_:

for ('10', '20', 'ff') {
    print hex, "\n";         # 16, 32, 255
}

Round-tripping a value through hex:

my $n = 0xC0FFEE;
my $s = sprintf "%x", $n;    # "c0ffee"
print hex $s;                # 12648430

Values that overflow native integer width warn and return a float:

use warnings;
my $big = hex 'ffffffffffffffffff';   # 19 'f's — too wide for u64
# "Integer overflow in hexadecimal number" warning
# $big is now an IEEE 754 double, with lost precision

Edge cases#

  • Non-hex characters terminate parsing. The first character that is not a hex digit, underscore, or recognised prefix ends the scan. Under use warnings this emits Illegal hexadecimal digit '…' ignored:

    use warnings;
    print hex '1f garbage';    # 31, with a warning
    print hex '0xAZ';          # 10, with a warning on 'Z'
    
  • Leading whitespace is not skipped. Unlike oct, hex treats whitespace as a non-hex character, so a leading space stops parsing before any digit is seen:

    print hex ' ff';           # 0
    
  • Empty string and undef return 0. An empty EXPR yields 0 with no warning. A bare undef yields 0 and emits the usual Use of uninitialized value warning under use warnings.

  • No sign handling. A leading - or + is a non-hex character and terminates parsing before any digit, so hex '-ff' returns 0. To parse a signed hex string, strip the sign yourself:

    my $s = '-ff';
    my $n = ($s =~ s/^-//) ? -hex($s) : hex($s);   # -255
    
  • Prefix forms. The accepted prefixes are 0x, 0X, x, and X. A lone 0 is not a prefix — it’s a digit. There is no # or $ prefix.

  • Case is irrelevant for the digits a-f and for the prefix letter x.

  • Underscore placement. A single underscore may precede each digit. Two consecutive underscores, a leading underscore before the prefix, or a trailing underscore terminate parsing as non-hex characters.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • oct — decodes strings with auto-detected base: 0x… as hex, 0b… as binary, 0… as octal, anything else as decimal. Use it when the input’s base is not known in advance

  • sprintf — the reverse direction; "%x" / "%X" format a number into a lowercase or uppercase hex string, "%#x" adds the 0x prefix, "%08x" zero-pads to a fixed width

  • printf — same "%x" formatting, written straight to a filehandle

  • pack — templates H (high nibble first) and h (low nibble first) convert between a hex-digit string and packed binary bytes; use these when moving hex data to and from a binary protocol

  • unpack — the inverse of pack; with "H*" it turns a byte string into a hex digit string in one call