rbc*_*bcc 59 c c++ java-native-interface
我正在使用JNI并且有一个jbyte类型的数组,其中jbyte表示为有符号字符,即-128到127.jbytes表示图像像素.对于图像处理,我们通常希望像素分量的范围为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);
Run Code Online (Sandbox Code Playgroud)
我很想知道如何在C和C++中做到这一点.
wic*_*ich 109
这是C++引入新的强制转换风格的原因之一,包括static_cast
和reinterpret_cast
你可以通过说明从有符号到无符号的转换来表示两件事,你可能意味着你希望无符号变量包含有符号变量的值,模数为无符号类型的最大值+ 1.这就是你的签名字符有一个值为-128然后CHAR_MAX+1
添加为值128,如果值为-1,则CHAR_MAX+1
添加值为255,这是static_cast所做的.另一方面,您可能意味着将某个变量引用的内存的位值解释为无符号字节,而不管系统上使用的有符号整数表示,即如果它具有位值0b10000000
,则应评估为值128 ,对于位值为255 0b11111111
,这是通过reinterpret_cast完成的.
现在,对于二进制补码表示,这恰好是完全相同的事情,因为-128表示为0b10000000
,-1表示为,0b11111111
并且同样表示它们之间的所有.然而,其他计算机(通常是较旧的架构)可能使用不同的签名表示,例如符号和数字或补码.在补码中,0b10000000
bitvalue不会是-128,而是-127,所以静态转换为unsigned char会使这129,而reinterpret_cast会使这128.另外在补码中0b11111111
bitvalue不会是-1,但是-0,(是的,这个值存在于'的补码中),并且将使用static_cast转换为值0,但使用reinterpret_cast将值转换为255.请注意,在1的补码的情况下,无符号值128实际上不能用有符号的char表示,因为它的范围是-127到127,因为-0值.
我不得不说绝大多数计算机都会使用两个补码,这使得整个问题几乎无处不在.你可能只会在非常古老的架构中看到除了两个补码以外的系统,想想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
Run Code Online (Sandbox Code Playgroud)
要用一个很好的C++方式用数组做到这一点:
jbyte memory_buffer[nr_pixels];
unsigned char* pixels = reinterpret_cast<unsigned char*>(memory_buffer);
Run Code Online (Sandbox Code Playgroud)
或C方式:
unsigned char* pixels = (unsigned char*)memory_buffer;
Run Code Online (Sandbox Code Playgroud)