在C中打印十六进制字符
我正在尝试读取一行字符,然后打印出该字符的十六进制等效值。
例如,如果我有一个字符串 "0xc0 0xc0 abc123"
,其中前 2 个字符为十六进制的 c0
,其余字符为 abc123
code> 以 ASCII 表示,那么我应该得到
c0 c0 61 62 63 31 32 33
然而,使用 %x
的 printf
给了我
ffffffc0 ffffffc0 61 62 63 31 32 33
如何在没有“ffffff”
?为什么只有 c0(和 80)有 ffffff
,而其他字符没有?
I'm trying to read in a line of characters, then print out the hexadecimal equivalent of the characters.
For example, if I have a string that is "0xc0 0xc0 abc123"
, where the first 2 characters are c0
in hex and the remaining characters are abc123
in ASCII, then I should get
c0 c0 61 62 63 31 32 33
However, printf
using %x
gives me
ffffffc0 ffffffc0 61 62 63 31 32 33
How do I get the output I want without the "ffffff"
? And why is it that only c0 (and 80) has the ffffff
, but not the other characters?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您看到
ffffff
是因为char
在您的系统上已签名。在 C 中,诸如printf
之类的可变参数函数会将所有小于int
的整数提升为int
。由于char
是一个整数(在您的情况下为 8 位有符号整数),因此您的字符将通过符号扩展提升为int
。由于
c0
和80
有一个前导 1 位(并且作为 8 位整数为负),因此它们正在进行符号扩展,而示例中的其他部分则没有t。这是一个解决方案:
这将屏蔽掉高位并仅保留您想要的低 8 位。
You are seeing the
ffffff
becausechar
is signed on your system. In C, vararg functions such asprintf
will promote all integers smaller thanint
toint
. Sincechar
is an integer (8-bit signed integer in your case), your chars are being promoted toint
via sign-extension.Since
c0
and80
have a leading 1-bit (and are negative as an 8-bit integer), they are being sign-extended while the others in your sample don't.Here's a solution:
This will mask out the upper bits and keep only the lower 8 bits that you want.
确实,有类型转换为int。
您还可以使用 %hhx 说明符强制类型为字符。
在大多数情况下,您还需要设置最小长度以用零填充第二个字符:
ISO/IEC 9899:201x 说:
Indeed, there is type conversion to int.
Also you can force type to char by using %hhx specifier.
In most cases you will want to set the minimum length as well to fill the second character with zeroes:
ISO/IEC 9899:201x says:
您可以创建一个无符号字符:
打印它会给出
C5
而不是ffffffc5
。只有大于 127 的字符才会用
ffffff
打印,因为它们是负数(字符有符号)。或者您可以在打印时强制转换
char
:You can create an unsigned char:
Printing it will give
C5
and notffffffc5
.Only the chars bigger than 127 are printed with the
ffffff
because they are negative (char is signed).Or you can cast the
char
while printing:您可以使用
hh
来告诉printf
表明参数是无符号字符。使用
0
获取零填充,使用2
将宽度设置为 2。x
或X
表示小写/大写十六进制字符。编辑:如果读者担心 2501 的断言,即这在某种程度上不是“正确”的格式说明符,我建议他们阅读
printf
链接再次。具体来说:至于他关于有符号与无符号的观点,在这种情况下并不重要,因为值必须始终为正数并且很容易适合有符号整数。无论如何,没有带符号的十六进制格式说明符。
编辑2:(“when-to-admit-you're-wrong”版本):
如果您阅读实际的 C11 标准 在第 311 页(PDF 的第 329 页)您会发现:
You can use
hh
to tellprintf
that the argument is an unsigned char. Use0
to get zero padding and2
to set the width to 2.x
orX
for lower/uppercase hex characters.Edit: If readers are concerned about 2501's assertion that this is somehow not the 'correct' format specifiers I suggest they read the
printf
link again. Specifically:As for his point about signed vs unsigned, in this case it does not matter since the values must always be positive and easily fit in a signed int. There is no signed hexideximal format specifier anyway.
Edit 2: ("when-to-admit-you're-wrong" edition):
If you read the actual C11 standard on page 311 (329 of the PDF) you find:
您可能将值 0xc0 存储在
char
变量中,这可能是有符号类型,并且您的值是负数(最高有效位集)。然后,在打印时,将其转换为int
,并且为了保持语义等价,编译器用 0xff 填充多余的字节,因此负数int
将具有相同的数值负char
的值。要解决此问题,只需在打印时转换为unsigned char
即可:You are probably storing the value 0xc0 in a
char
variable, what is probably a signed type, and your value is negative (most significant bit set). Then, when printing, it is converted toint
, and to keep the semantical equivalence, the compiler pads the extra bytes with 0xff, so the negativeint
will have the same numerical value of your negativechar
. To fix this, just cast tounsigned char
when printing:您可能正在从带符号的字符数组进行打印。从无符号字符数组打印或用 0xff 屏蔽该值:例如 ar[i] & 0xFF。由于设置了高(符号)位,因此 c0 值正在进行符号扩展。
You are probably printing from a signed char array. Either print from an unsigned char array or mask the value with 0xff: e.g. ar[i] & 0xFF. The c0 values are being sign extended because the high (sign) bit is set.
尝试这样的事情:
产生这样的结果:
Try something like this:
Which produces this:
这是一个帮助说明符号扩展的程序。请注意,十六进制中的 0 - 127(0 到 0111 1111)按预期显示,因为符号位为 0,因此当从 8 位到 32 位时,它会用 0 进行扩展(在十六进制中显示为空白)。一旦达到 128 (1000 000) 个有符号字符,它就变成负数 (-128),并且用 1/F 进行符号扩展。
程序:
即使超过 127,无符号字符也会用 0 扩展,因为您已明确告诉它它是一个正数。
当将有符号字符打印为有符号整数时,您可以看到符号扩展如何保留 -128 的值。
(编辑:将二进制列添加到示例输出中,稍后将其包含在程序代码中)
Here's an program to help illustrate sign extension. Note that 0 - 127 (0 to 0111 1111) in hex shows as expected, because the sign bit is 0, so when going from 8-bit to 32-bit its extended with 0's (which show as blank in the hex). Once you get to 128 (1000 000) signed char, it becomes a negative number (-128), and it is sign-extended with 1's / F's.
Program:
Unsigned char gets extended with 0's even when going over 127, because you've explicitly told it that its a positive number.
When printing the signed char, as a signed integer, you can see how sign-extending is preserving the value of -128.
(edit: added binary column to the example output, will include this in the program code later)