1

I'm trying to pack a byte array into a string using array.pack("C") but I'm getting some weird values pack. For example, when I say [7].pack("C"), the return value is "\a", whereas when I say "\x07".unpack("C"), the return value is [7], which is the desired behavior.

[6].pack("C") for example returns "\x06", again the desired outcome, whereas [33].pack("C") returns "!".

I'm new to bytes and hex in general. What is happening here? In my understanding, [33].pack("C") should return "\x21".

2 Answers 2

3

Why would it return "\x21"? The \x notation is reserved for non-printable characters, but since \x21 is equivalent to ! then that's what's displayed.

The inspect version of a string is generally the most readable version of it, not the most literal.

Likewise:

"!".ord
# => 33
"\x21".ord
# => 33
"\x21".ord.to_s(16)
# => "21"
33.chr
# => "!"

There's a number of special characters documented in the Strings section:

\a             bell, ASCII 07h (BEL)
\b             backspace, ASCII 08h (BS)
\t             horizontal tab, ASCII 09h (TAB)
\n             newline (line feed), ASCII 0Ah (LF)
\v             vertical tab, ASCII 0Bh (VT)
\f             form feed, ASCII 0Ch (FF)
\r             carriage return, ASCII 0Dh (CR)
\e             escape, ASCII 1Bh (ESC)
\s             space, ASCII 20h (SPC)
\\             backslash, \
\nnn           octal bit pattern, where nnn is 1-3 octal digits ([0-7])
\xnn           hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F])
\unnnn         Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
\u{nnnn ...}   Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F])
\cx or \C-x    control character, where x is an ASCII printable character
Sign up to request clarification or add additional context in comments.

Comments

2

These strings are fully equivalent, they are just different representation if exactly the same bytes:

"\a" == "\x07"
# => true

"\x21" == "!"
# => true

If you have a look at the ASCII table, you'll see that the hex 21 (decimal 33) is represented by the exclamation mark character. Similarly, the hex 7 (and decimal 7) character is represented by a control character called BEL (bell) which us usually represented as "\a".

In general, Ruby choses the most generic representation of strings when printing them. There will always be other (equivalent) representations you can use in your code. However, the will always map back to the exact same bytes in memory.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.