我再次面临格式问题。我想将端口号(作为整数)作为参数传递给函数(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
答案 0 :(得分:1)
在大多数系统上,int
的大小为4字节32位。 1234
的十六进制表示形式为0x000004d2
。在小端系统上(例如x86和x86-64),它以四个字节0xd2
,0x04
,0x00
和0x00
的形式存储在内存中订单。
如果我们将其视为字节数组,则看起来像
+------+------+------+------+ | 0xd2 | 0x04 | 0x00 | 0x00 | +------+------+------+------+
您遇到三个问题:
int
的所有四个字节上循环,而只需要有效位char
已被签名,当升级为int
时,它将被符号扩展(根据two's complement规则)要解决第一点,您需要舍弃“前导”零字节。
要解决第二点,您需要从 end 循环(但仅限于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
}
答案 1 :(得分:0)
摆脱签名并修改格式。
void foo(int port, int endianess)
{
unsigned char * _port = (unsigned char*)&port;
if(endianess)
{
for (size_t i = 0; i < 2; i++)
{
printf("\\x%02hhx", _port[i]);
}
}
else
{
for (size_t i = sizeof(port) - 1; i >= sizeof(port) - 2; i--)
{
printf("\\x%02hhx", _port[i]);
}
}
}