我主演在原来的JPEG标准(ITU 81),特别是图中图F.12:移带负号的值是未定义的
参考:以V延伸的解码值的符号位在SLL
术语表示:shift left logical operation
(见PDF第15页)
现在著名的libjpeg执行决定实施它this way(相当直接转录):
/*
* Figure F.12: extend sign bit.
* On some machines, a shift and add will be faster than a table lookup.
*/
#ifdef AVOID_TABLES
#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
#else
#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
static const int extend_test[16] = /* entry n is 2**(n-1) */
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
#endif /* AVOID_TABLES */
很明显移位负符号值UB,所以我想知道什么JPEG标准的原作者居然在这里的意思。 JPEG标准是否限于二进制补码表示?
据我所知,移位一个负符号值是实现定义的(只要移位量为正数且在'sizeof(operator)* CHAR_BIT'内) – bolov
@bolov,* right * - 移动一个负值是实现定义的。 *另一方面,左移*移动签名类型的值的方法是***未定义的,除非原始值是非负数,并且数学结果可以在结果类型中表示。特别是,OP十分正确,左移-1产生UB。 –
@JohnBollinger谢谢。总有一些事情需要重新学习C或C++。 – bolov