从signed char转换为unsigned char并返回?
我正在使用JNI,并有一个jbyte类型的数组,其中jbyte表示为一个有符号的字符,即从-128到127.Jbytes表示图像像素。 对于图像处理,我们通常希望像素分量的范围从0到255.因此,我想将jbyte值转换为0到255的范围(即与无符号字符的范围相同),对值进行一些计算,然后存储再次结果为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
和reinterpret_cast
的新投射风格的原因之一
有两件事你可以说从signed到unsigned的转换,你可能意味着你希望unsigned变量包含有符号变量的值,以你的无符号类型+ 1的最大值为模。就是说,如果你的signed char有一个值为-128,那么CHAR_MAX+1
被添加为128的值,如果它的值为-1,那么CHAR_MAX+1
被添加为值255,这是由static_cast完成的。 另一方面,无论系统上使用的带符号整数表示,即它是否具有位值0b10000000
它都应该将值解释为无符号字节128位和255位值为0b11111111
,这是通过reinterpret_cast完成的。
现在,对于二进制补码表示,这恰好是完全相同的事情,因为-128表示为0b10000000
而-1表示为0b11111111
,对于所有这两者之间也是如此。 然而,其他计算机(通常是较旧的架构)可能会使用不同的符号表示法,如符号和大小或补码。 在补码中, 0b10000000
比特值不会是-128,而是-127,所以静态转换为无符号字符会使此129,而reinterpret_cast会使此128.此外,在补码0b11111111
值不会是-1 ,但是-0(是的,这个值存在于'补码'中),并且会被static_cast转换为值0,但是具有reinterpret_cast的值将被转换为255。 请注意,在1的补码情况下,128的无符号值实际上不能用有符号字符表示,因为它的值从-07到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
要用一个很好的C ++方式来处理数组:
jbyte memory_buffer[nr_pixels];
unsigned char* pixels = reinterpret_cast<unsigned char*>(memory_buffer);
或C方式:
unsigned char* pixels = (unsigned char*)memory_buffer;
是的,这是安全的。
c语言在执行计算之前使用称为整数提升的特性来增加值中的位数。 因此,您的CLAMP255宏将以整数(可能是32位)精度运行。 结果被分配给一个jbyte,它将整数精度降低到8位,以适应jbyte。
你是否意识到,对于v <0,CLAMP255返回0,对于v> = 0,则返回255?
恕我直言,CLAMP255应该定义为:
#define CLAMP255(v) (v > 255 ? 255 : (v < 0 ? 0 : v))
差异:如果v不大于255且不小于0:返回v而不是255
链接地址: http://www.djcxy.com/p/96701.html上一篇: Converting from signed char to unsigned char and back again?