在 Java 中表示 C 左移 signed char 与 unsigned char
Representing C shift left signed char vs. unsigned char in Java
我正在尝试将一些 C 代码移植到 Java 中,并且一直在努力解释转换顺序、运算符优先级,并确保结果符合我的预期。我已经阅读了很多帖子并认为我已经弄明白了,但我想确保我已经正确地表达了它。
我要移植的 original C code 是这样的:
UInt32 _strtoul(char *str, int size, int base)
{
UInt32 total = 0;
int i;
for (i = 0; i < size; i++)
{
if (base == 16)
total += str[i] << (size - 1 - i) * 8;
else
total += ((unsigned char) (str[i]) << (size - 1 - i) * 8);
}
return total;
}
在代码中,将一个 4 字节的值(字节数组或字符串)转换为 32 位整数。我试图理解条件句中两个子句的区别;具体来说,(unsigned char)
演员表的实际效果是什么。
据我了解,在 C 中,字节在左移之前被提升为 int。但是,我不明白它是如何转化为 C 中的按位表示的。在顶部分支(base == 16,有符号)中提升字节值 0xff (-1) 是否正确从 0xff 到 0xffffffff 而在底部分支(无符号)中,值 0xff (255) 将从 0xff 提升到 0x000000ff?
鉴于此解释,以下 Java 代码是否是忠实的表示(Uint 与 int return 类型除外)?
public static int strtoul(byte[] bytes, int size, int base) {
int total = 0;
for (int i = 0; i < size; i++) {
if (base == 16) {
// signed bytes, shifted
total += bytes[i] << (size - 1 - i) * 8;
} else {
// unsigned bytes, shifted
total += bytes[i] & 0xff << (size - 1 - i) * 8;
}
}
return total;
}
我没有使用 sscanf,因为您正在明确寻找 uint32 解决方案。如果你真的不在乎,它就像
一样简单
#include <stdio.h>
unsigned int _strtoui(char *s)
{
unsigned int ret;
sscanf(str, "%u", &ret); /* use "%x" for hexadecimal */
return ret;
}
我想 Java 中有类似 sscanf 的东西。无论如何,这是我对 uint32_t
/UInt32
的解决方案。当心输入数据中的溢出。此外,如果字符不是(十六进制)数字,这些函数将给出废话。改进它是另一项练习。
#include <stdint.h>
uint32_t _strtoui32(char *str)
{
int i;
uint32_t total = 0;
for(i=0; str[i] != '[=11=]'; i++)
total = total*10 + str[i] - '0';
return total;
}
uint32_t _hextoui32(char *str)
{
int i;
uint32_t total = 0;
for(i=0; str[i] != '[=11=]'; i++) {
total *= 16;
if(str[i] > 47 && str[i] < 58) /* base 10 number */
total += str[i] - '0';
else if(str[i] > 64 && str[i] < 71) /* uppercase A-F */
total += str[i] - 'A' + 10;
else /* lowercase a-f */
total += str[i] - 'a' + 10;
}
return total;
}
uint32_t _hstrtoui32(char *str, int base)
{
if(base == 16)
return _hextoui32(str);
else
return _strtoui32(str);
}
根据 Java's operator precedence,您需要在 bytes[i] & 0xff
周围加上括号,否则它会被解析为 bytes[i] & (0xff << (size - 1 - i) * 8)
.
所以最后你的代码应该是这样的:
public static int strtoul(byte[] bytes, int size, int base) {
int total = 0;
for (int i = 0; i < size; i++) {
if (base == 16) {
// signed bytes, shifted
total += bytes[i] << (size - 1 - i) * 8;
} else {
// unsigned bytes, shifted
total += (bytes[i] & 0xff) << (size - 1 - i) * 8;
}
}
return total;
}
我正在尝试将一些 C 代码移植到 Java 中,并且一直在努力解释转换顺序、运算符优先级,并确保结果符合我的预期。我已经阅读了很多帖子并认为我已经弄明白了,但我想确保我已经正确地表达了它。
我要移植的 original C code 是这样的:
UInt32 _strtoul(char *str, int size, int base)
{
UInt32 total = 0;
int i;
for (i = 0; i < size; i++)
{
if (base == 16)
total += str[i] << (size - 1 - i) * 8;
else
total += ((unsigned char) (str[i]) << (size - 1 - i) * 8);
}
return total;
}
在代码中,将一个 4 字节的值(字节数组或字符串)转换为 32 位整数。我试图理解条件句中两个子句的区别;具体来说,(unsigned char)
演员表的实际效果是什么。
据我了解,在 C 中,字节在左移之前被提升为 int。但是,我不明白它是如何转化为 C 中的按位表示的。在顶部分支(base == 16,有符号)中提升字节值 0xff (-1) 是否正确从 0xff 到 0xffffffff 而在底部分支(无符号)中,值 0xff (255) 将从 0xff 提升到 0x000000ff?
鉴于此解释,以下 Java 代码是否是忠实的表示(Uint 与 int return 类型除外)?
public static int strtoul(byte[] bytes, int size, int base) {
int total = 0;
for (int i = 0; i < size; i++) {
if (base == 16) {
// signed bytes, shifted
total += bytes[i] << (size - 1 - i) * 8;
} else {
// unsigned bytes, shifted
total += bytes[i] & 0xff << (size - 1 - i) * 8;
}
}
return total;
}
我没有使用 sscanf,因为您正在明确寻找 uint32 解决方案。如果你真的不在乎,它就像
一样简单#include <stdio.h>
unsigned int _strtoui(char *s)
{
unsigned int ret;
sscanf(str, "%u", &ret); /* use "%x" for hexadecimal */
return ret;
}
我想 Java 中有类似 sscanf 的东西。无论如何,这是我对 uint32_t
/UInt32
的解决方案。当心输入数据中的溢出。此外,如果字符不是(十六进制)数字,这些函数将给出废话。改进它是另一项练习。
#include <stdint.h>
uint32_t _strtoui32(char *str)
{
int i;
uint32_t total = 0;
for(i=0; str[i] != '[=11=]'; i++)
total = total*10 + str[i] - '0';
return total;
}
uint32_t _hextoui32(char *str)
{
int i;
uint32_t total = 0;
for(i=0; str[i] != '[=11=]'; i++) {
total *= 16;
if(str[i] > 47 && str[i] < 58) /* base 10 number */
total += str[i] - '0';
else if(str[i] > 64 && str[i] < 71) /* uppercase A-F */
total += str[i] - 'A' + 10;
else /* lowercase a-f */
total += str[i] - 'a' + 10;
}
return total;
}
uint32_t _hstrtoui32(char *str, int base)
{
if(base == 16)
return _hextoui32(str);
else
return _strtoui32(str);
}
根据 Java's operator precedence,您需要在 bytes[i] & 0xff
周围加上括号,否则它会被解析为 bytes[i] & (0xff << (size - 1 - i) * 8)
.
所以最后你的代码应该是这样的:
public static int strtoul(byte[] bytes, int size, int base) {
int total = 0;
for (int i = 0; i < size; i++) {
if (base == 16) {
// signed bytes, shifted
total += bytes[i] << (size - 1 - i) * 8;
} else {
// unsigned bytes, shifted
total += (bytes[i] & 0xff) << (size - 1 - i) * 8;
}
}
return total;
}