0 转换为 128
0 is converted to 128
我正在尝试从主机 Linux 到目标系统执行 SNMP 设置。但是,设置的不是正确的值,而是错误的值。经过一番研究,我做了这个 table:
Linuxsnmp
中十进制值的十六进制表示
0 - 0x80 - 1000 0000 - 0 is converted to 128
1 - 0x40 - 0100 0000 - 1 is converted to 64
2 0x20 - 0010 0000 - 2 is converted to 32
3 0x10 - 0001 0000 - 3 is converted to 16
4 0x08 - 0000 1000 - 4 is converted to 8
5 0x04 - 0000 0100 - 5 is converted to 4
6 0x02 - 0000 0010 - 6 is converted to 2
7 0x01 - 0000 0001 - is converted to 1
目标系统中十进制值的十六进制表示
0 - 0x00 - 0000 0000
1 - 0x01 - 0000 0001
2 0x02 - 0000 0010
3 0x03 - 0000 0011
4 0x04 - 0000 0100
5 0x05 - 0000 0101
6 0x06 - 0000 0110
7 0x07 - 0000 0111
我有两个问题:
- 这个问题背后的原因可能是什么?
- 有人知道如何在 C 程序中将这些 Linux 值转换为正确的目标值吗?
如果我正确理解你的问题,你会收到一个使用单热编码对 8 个值(0 到 7)进行编码的字节。请参阅 https://en.wikipedia.org/wiki/One-hot(注意:您的位顺序似乎颠倒了)。
如果您只是将单热编码位模式放入目标系统上的字节变量中,您将不会获得原始值,因为您的目标系统使用另一种编码(可能是 2 的补码)。换句话说 - 给定的位模式在单热编码和 2 的补码编码中具有不同的含义。
所以任务是将单热编码值转换为目标系统上的等效值。
你可以选择一个简单的 switch 语句——比如:
int main(void)
{
unsigned char linux_snmp_value = 0x20;
unsigned char target_value = 255;
switch(linux_snmp_value)
{
case 0x80:
target_value = 0;
break;
case 0x40:
target_value = 1;
break;
case 0x20:
target_value = 2;
break;
// Add the remaining cases here
default:
// Illegal value
// Add some error handling
break;
}
printf("Target value %d\n", target_value);
return 0;
}
如果你更喜欢循环,它可能是这样的:
int main(void)
{
unsigned char linux_snmp_value = 0x01;
unsigned char target_value = 0;
unsigned char mask = 0x80;
while (mask)
{
if (mask == linux_snmp_value) break;
++target_value;
mask = mask >> 1;
}
if (mask == 0)
{
// Illegal value
// Add some error handling
printf("ERROR\n");
return -1;
}
printf("Target value %d\n", target_value);
return 0;
}
如果可移植性不是问题(例如你不在 VAX 或 AVR8 机器上编译)你可以使用机器指令
asm (“bsrl %1, %0” : “=r” (position) : “r” (number));
你也可以把它包装成漂亮的内联函数。
类似的指令在 ARM、MIPS、PIC 和许多其他指令上可用。
我正在尝试从主机 Linux 到目标系统执行 SNMP 设置。但是,设置的不是正确的值,而是错误的值。经过一番研究,我做了这个 table:
Linuxsnmp
中十进制值的十六进制表示0 - 0x80 - 1000 0000 - 0 is converted to 128
1 - 0x40 - 0100 0000 - 1 is converted to 64
2 0x20 - 0010 0000 - 2 is converted to 32
3 0x10 - 0001 0000 - 3 is converted to 16
4 0x08 - 0000 1000 - 4 is converted to 8
5 0x04 - 0000 0100 - 5 is converted to 4
6 0x02 - 0000 0010 - 6 is converted to 2
7 0x01 - 0000 0001 - is converted to 1
目标系统中十进制值的十六进制表示
0 - 0x00 - 0000 0000
1 - 0x01 - 0000 0001
2 0x02 - 0000 0010
3 0x03 - 0000 0011
4 0x04 - 0000 0100
5 0x05 - 0000 0101
6 0x06 - 0000 0110
7 0x07 - 0000 0111
我有两个问题:
- 这个问题背后的原因可能是什么?
- 有人知道如何在 C 程序中将这些 Linux 值转换为正确的目标值吗?
如果我正确理解你的问题,你会收到一个使用单热编码对 8 个值(0 到 7)进行编码的字节。请参阅 https://en.wikipedia.org/wiki/One-hot(注意:您的位顺序似乎颠倒了)。
如果您只是将单热编码位模式放入目标系统上的字节变量中,您将不会获得原始值,因为您的目标系统使用另一种编码(可能是 2 的补码)。换句话说 - 给定的位模式在单热编码和 2 的补码编码中具有不同的含义。
所以任务是将单热编码值转换为目标系统上的等效值。
你可以选择一个简单的 switch 语句——比如:
int main(void)
{
unsigned char linux_snmp_value = 0x20;
unsigned char target_value = 255;
switch(linux_snmp_value)
{
case 0x80:
target_value = 0;
break;
case 0x40:
target_value = 1;
break;
case 0x20:
target_value = 2;
break;
// Add the remaining cases here
default:
// Illegal value
// Add some error handling
break;
}
printf("Target value %d\n", target_value);
return 0;
}
如果你更喜欢循环,它可能是这样的:
int main(void)
{
unsigned char linux_snmp_value = 0x01;
unsigned char target_value = 0;
unsigned char mask = 0x80;
while (mask)
{
if (mask == linux_snmp_value) break;
++target_value;
mask = mask >> 1;
}
if (mask == 0)
{
// Illegal value
// Add some error handling
printf("ERROR\n");
return -1;
}
printf("Target value %d\n", target_value);
return 0;
}
如果可移植性不是问题(例如你不在 VAX 或 AVR8 机器上编译)你可以使用机器指令
asm (“bsrl %1, %0” : “=r” (position) : “r” (number));
你也可以把它包装成漂亮的内联函数。 类似的指令在 ARM、MIPS、PIC 和许多其他指令上可用。