uint8* CIwTexture::GetTexels() const;
例如,如果将返回值强制转换为uint32*
,那么转换如何在此处工作?如果返回值只是8位,如何将指向8位数据的指针转换为32位?
答案 0 :(得分:2)
指针只是地址作为其值的变量。这意味着所有指针都具有相同的大小(不要混淆“所有指针'数据具有相同的大小”,这不是真的)。
编译器需要处理指针指向的数据的所有信息都是从其类型推断出来的。这意味着uint32_t
指向的数据将被视为32位数据,uint8_t
将被视为8位数据。
所有这些信息仅保存在编译时,编译器根据它正在处理的指针生成机器代码。这意味着从指向另一个的指针强制仅与编译器相关,因此它知道在生成代码时如何处理数据。在运行时,没有任何更改,也不会复制或移动任何值。
粗略地说,你的内存布局可能如下所示:
括号部分(数据的大小)是编译器的提示,因此它可以按程序员的意图处理数据。
当您转换为uint32_t
时,您的内存布局大致如下所示:
现在,您可以从中推断出一些事情:
最后,考虑以32位访问此数据的含义:
答案 1 :(得分:1)
例如,如果它投射到uin32 *,那么投射如何在这里工作?我的意思是如果返回只有8位,如何将指向8位数据的指针转换为32位?
它返回一个存储器地址,而不是存储在该存储器地址的8位。那个地址指向内存中的某个地方。当您将其分配给uint32*
时,它仍然指向相同的内存位置。
现在,当您对该指针进行dedeferrence时,它将从指针指向的地址的4个连续内存位置读取值(将其与您将取消引用uint8
的情况进行比较,并且它只能读取一个)。
// somewhere in the memory
uint32 x;
uint8_t* foo()
{
// Now imagine here x being constructed from
// individual bytes or somehow
// ...
// return pointer to the first byte of x as `uint8_t`
return (uint8_t*)&x;
}
现在,这里的问题出现在调用者方面 - 函数签名中没有任何内容告诉调用者他需要/可以将其视为uint32_t
。在这种情况下,必须明确记录。
答案 2 :(得分:0)
返回值是指向uint8的指针。 C ++中的指针可以转换为任何其他类型的指针。 "魔术"取消引用此指针时启动 - 并且取消引用返回的值是指针的类型。例如,如果你这样做:
uint32* ptr = (uint32*)functionThatReturnsPtrToUint8();
uint32 value = *ptr;
然后"值"变量将只占用ptr指向的前4个字节,并将它们转换为uint32值(这完全取决于底层系统端)。
答案 3 :(得分:0)
回报不是8位。返回是一个指针(一个内存地址)。指针的类型告诉编译器如何查看内存。在这种情况下,它表示应该一次处理一个字节的内存。如果将指针强制转换为uint32*
,则告诉编译器将数据视为四个字节的块。但是,该函数返回一个指向字节的指针。数据可能不打算用四个字节的块来处理。如果将指针强制转换为其他类型,则告诉编译器以可能无意的方式使用数据。
答案 4 :(得分:0)
指针只是地址,转换类型不会改变地址(指针的值),而是给编译器提示。
但是,当您将指针转换为不同类型时,您会遇到对齐问题,并且编译器会抱怨。根本问题是对于某些架构,您必须以正确的对齐方式访问内存,例如,您不能取消引用奇数地址,否则CPU可能会出错/陷阱。
如果您知道自己在做什么,可以安全地忽略它(在这种情况下,我假设返回的指针正确对齐)。
最后,要投射你刚才做的指针:
uint32_t* p = (uint32_t*) mem;
或
uint32_t* p = static_cast<uint32_t*>( mem );