c - 以特殊的十六进制格式显示整数
问题描述
我再次面临格式问题。我想将端口号(作为整数)作为参数传递给函数(argv[]),并希望以特殊格式显示它。在我的实际情况下,我想以十六进制显示端口号 1234。我这样试试
int port = 1234;
char* _port = (char*)&port;
for (int i = 0; i < sizeof(port); i++) {
printf("\\x%02x", _port[i]);
}
但它显示
\xffffffd2\x04\x00\x00
但我希望它的格式带有前导零和 2 位数字,例如
\x04\xd2
你能帮我吗?
编辑:我把它改成
sizeof(port)-2
它只显示 2 位数字,但字节序错误:S
解决方案
在大多数系统上,大小int
为 4 个字节,32 位。的十六进制表示1234
是0x000004d2
。在 little-endian 系统(如 x86 和 x86-64)上,它像四个字节0xd2
、0x04
和那样0x00
存储在内存中。0x00
如果我们把它看成一个字节数组,它看起来像
+------+------+------+------+ | 0xd2 | 0x04 | 0x00 | 0x00 | +------+------+------+------+
你有三个问题:
- 您循环遍历 的所有四个字节
int
,而您只需要有效位 - 你不考虑字节序
char
您系统上的那个是签名的,当提升到int
它时将被符号扩展(根据二进制补码规则)
要解决第一点,您需要丢弃“前导”零字节。
要解决第二点,您需要从末尾循环(但仅在 little-endian 系统上)。
要解决第三点,请使用不会进行符号扩展的类型(即uint8_t
)。
放在一起你可以做这样的事情:
// The number we want to print
int port = 1234;
// Copy the raw binary data to a buffer
// This buffer is to not break strict aliasing
uint8_t _port[sizeof port];
memcpy(_port, &port, sizeof port);
// Skip leading zeroes in the buffer
// This is done by looping from the end of the buffer to the beginning,
// and loop as long as the current byte is zero
uint8_t *current;
for (current = _port + sizeof _port - 1; current > _port && *current == 0; --current)
{
// Empty
}
// Print the remaining bytes
for (; current >= _port; --current)
{
printf("\\x%02x", *current); // Print with zero-padding, so e.g. \x4 becomes \x04
}
推荐阅读
- amazon-s3 - 如何处理从云端下载的浏览器缓存
- spring-data-jpa - 带有@OneToMany 的 JPA EmbeddedId - 无法使用 JOIN 进行查询
- firebase - 如果某人的数据不包含特定密钥,我如何防止他写?
- javascript - 页面加载后,Jquery,Django,Infinite Scroll 加载其余元素
- html - 将项目与对齐内容对齐
- angular - 如何在角度使用 3rd 方节点包?
- getstream-io - 在 getstream 中聚合更新组中的活动
- php - 使用 php 发送电子邮件后无法重定向到另一个页面
- mysql - 计算具有相同 MySQL 的 3 列值的行的出现次数
- python - Python:计算数字变化的次数