我正在使用 JNI 并有一个 jbyte 类型的数组,其中 jbyte 表示为有符号字符,即范围从 -128 到 127。 jbyte 表示图像像素。对于图像处理,我们通常希望像素分量的范围为0到255。因此,我想将jbyte值转换为0到255的范围(即与unsigned char相同的范围),对该值进行一些计算,然后存储结果再次为 jbyte。
我怎样才能安全地进行这些转换?
我设法让这段代码工作,其中像素值增加 30 但限制为值 255,但我不明白它是否安全或可移植:
#define CLAMP255(v) (v > 255 ? 255 : (v < 0 ? 0 : v))
jbyte pixel = ...
pixel = CLAMP_255((unsigned char)pixel + 30);
我有兴趣知道如何在 C 和 C++ 中执行此操作。
这就是 C++ 引入新的强制转换风格的原因之一,其中包括static_cast
and reinterpret_cast
说从有符号到无符号的转换可以表示两件事,您可能意味着您希望无符号变量包含有符号变量的值模无符号类型的最大值 + 1。也就是说,如果您的有符号 char 有一个那么值为-128CHAR_MAX+1
添加值为 128,如果它的值为 -1,则CHAR_MAX+1
添加值为 255,这是 static_cast 完成的。另一方面,您可能意味着将某些变量引用的内存的位值解释为无符号字节,无论系统上使用的有符号整数表示如何,即如果它具有位值0b10000000
它的值应为 128,位值应为 2550b11111111
,这是通过reinterpret_cast 完成的。
现在,对于两个补码表示,这恰好是完全相同的事情,因为 -128 表示为0b10000000
-1 表示为0b11111111
对于介于两者之间的所有情况也是如此。然而,其他计算机(通常是较旧的体系结构)可能使用不同的符号表示形式,例如符号和数值或补码。补足0b10000000
bitvalue 不会是 -128,而是 -127,因此静态转换为 unsigned char 会得到 129,而 reinterpret_cast 会得到 128。另外,在补码中0b11111111
bitvalue 不会是 -1,而是 -0(是的,这个值存在于补码中),并且会使用 static_cast 转换为 0 值,而使用interpret_cast 转换为 255 值。请注意,在补码的情况下,无符号值 128 实际上不能用有符号字符表示,因为由于 -0 值,它的范围从 -127 到 127。
我不得不说,绝大多数计算机将使用二进制补码,这使得整个问题在您的代码运行的任何地方都毫无意义。您可能只会在非常古老的架构中看到除二进制补码以外的任何系统,想想 60 年代的时间框架。
语法归结为以下内容:
signed char x = -100;
unsigned char y;
y = (unsigned char)x; // C static
y = *(unsigned char*)(&x); // C reinterpret
y = static_cast<unsigned char>(x); // C++ static
y = reinterpret_cast<unsigned char&>(x); // C++ reinterpret
要使用数组以良好的 C++ 方式执行此操作:
jbyte memory_buffer[nr_pixels];
unsigned char* pixels = reinterpret_cast<unsigned char*>(memory_buffer);
或 C 方式:
unsigned char* pixels = (unsigned char*)memory_buffer;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)