如何位移U16*的数据?

how to bit shift a u16*'s data?

本文关键字:数据 何位移 U16      更新时间:2023-10-16

对不起,如果这没有任何意义,但我正在尽我最大的努力去理解它。

我基本上有一个指向openGL纹理数据的指针,它是16 bpp (pcx.image)。我需要为每个像素打开alpha位。所以我想出了这个,但正如你所看到的,它真的很糟糕。

for(int i = 0; i < (TEXTURE_SIZE_128 * TEXTURE_SIZE_128); i++){
        pcx.image.data16 |=  1 << ((16 * i) + 15);
    }

我得到这些错误:

c:/Users/me/Desktop/neronds/source/neroedge.cpp:40:43: error: invalid operands of types 'u16* {aka short unsigned int*}' and 'int' to binary 'operator|'
c:/Users/me/Desktop/neronds/source/neroedge.cpp:40:43: error:   in evaluation of 'operator|=(u16* {aka short unsigned int*}, int)'

我如何得到修复这些错误,我在正确的轨道上改变每像素的alpha位?

试试这个:

for(unsigned i = 0; i < (TEXTURE_SIZE_128 * TEXTURE_SIZE_128); i++)
    {
        constexpr u16 ALPHA_BIT = 1 << 15;
        pcx.image.data16[i] |= ALPHA_BIT;
    }

如果您的编译器还不支持constexpr (c++11的一个特性),请使用const

你已经得到了如何修复它的答案,但没有解释为什么你的代码是错误的。让我们看一下这段代码:

pcx.image.data16 |=  1 << ((16 * i) + 15);

很明显,你认为编译器将数组视为由单个位组成的长字符串。同时你也陷入了可以任意长时间移动的误解中。然而,这不是C和c++的工作方式。位移只适用于它所应用的类型的宽度。根据参与的类型,编译器使用的类型有一些规则。那么让我们来分解这些类型:

(int) << (((int) * (int)) + (int));

好的,这里只有int,所以操作的类型将是int。根据平台的不同,只有有限的位数。但为了方便起见,我们假设int有64位。这意味着任何大于65位的1的左移都将从可用的位中移出该位,并且您将得到零位集。但我们还没做完呢。

之后,你将int分配给uint16_t。下面是下一个误解。uint16_t类型被指定为提供至少16位 (C在这些事情上不是很精确,因为它可能运行在字长不是8位的倍数的平台上)。但是为了便于解释,我们假设它正好是16位。赋值

(uint16_t) = (int)

进行强制转换,即丢弃不适合L值的位。

最后但并非最不重要:表达式pcx.image.data16是一个指针。该指针指向数据数组的第一个元素。通过给这个指针赋值,你只改变了这个指针,而不是它所指向的数据。所以你必须取消对指针的引用。可以通过在指针前加上*或附加索引操作符[…]来解引用指针。注意*[0]是相同的!如果你做了

 *pcx.image.data16;

这只会解引用第一个数组元素(可能有16位,但可能更多)。无论如何:你不能给它赋一个更大的位向量,这会"包装"到下一个元素中(这是一件好事!)。

因此,解决方案是,遍历数组的所有元素,并为每个元素设置额外的位:

for(int i = 0; i < (TEXTURE_SIZE_128 * TEXTURE_SIZE_128); i++){
    pcx.image.data16[i] |=  1 << 15;
}