繁体   English   中英

将 unsigned short * 转换为 unsigned int *

[英]Cast unsigned short * to unsigned int *

我正在学习 C++,我有一个关于 cast 的问题。 我有一个 unsigned short * 我想把它转换成一个 unsigned int * 但我没有相同的值,我想知道为什么。

当我将一个 short 转换为一个 int(使用静态转换)时,我具有相同的值,但它不适用于 unsigned short * 到 unsigned int *

所以我试着理解为什么,一个 short 是 4 个字节,一个 int 可以是 8. 16 或 32? 所以指针每次都会进入内存? 但是为什么从 short 转换为 int 有效呢?

unsigned short *a = something(); // something return me a unsigned short *a

unsigned int *b = static_cast<unsigned int *>(a); // I also tried with reintepret_cast

std::cout << *a << std::endl // (print me my first value)
std::cout << *b << std::endl // (print me a wrong value)

结果不同......有人可以解释我为什么以及如何解决这个问题吗?

非常感谢,

在 C++ 中将一种指针转换为另一种然后取消引用它是“未定义的行为”; 你不被允许这样做并期待理智的结果。

在这种特定情况下,强制转换基本上是对指向的地址处的数据字节进行重新解释。 在生成的机器代码级别,问题在于int在您的系统上需要 4 个字节,而short仅为 2 个; 所以你阅读了short的结尾并获得了垃圾数据。

在比生成的机器代码更高的抽象上也存在问题(上述未定义行为并不意味着“好吧,你读错了内存”,这是一种温和的可能性;真正疯狂的事情可能会发生,包括时间旅行,但这不是笑话)。 但这就足够了。

当您将实际的int转换为short (或无符号的等价物)时,该语言实际上采用short的内容并将其扩展以填充int

没有办法采用unsigned short*并且在不创建指向的独立资源的情况下获得unsigned int*

C++ 中的指针就像街道地址。 int是写字楼, short是平房。 如果你有一间平房的地址,然后在上面潦草地写上“这是一栋办公楼”,那是不真实的。 而当有人去平房盲目地使用电梯时,事情就变得不对劲了。

另一方面,如果你有一座平房,并说“把它建成办公楼”(一个实际的 short 到 int 的转换),那是可以做到的。 你得到一栋不同的建筑(因为办公楼不适合平房),但它适合平房的所有东西。


现在,通常允许您将指针转换为对齐程度较低的指针,只要您在使用它们之前将指针转换回来 (.)。

在某些狭窄的情况下,您可以取消引用指针。

  1. char*可用于读取某些类型(以及std::byte*等)的“原始内存”。

写入此类字节以复制对象仅在它们“可平凡复制”时才有效。

  1. 在某些情况下,指向一种类型前缀的指针可用于读取另一种类型。

这就是所谓的“布局兼容”,规则比大多数人想象的更具体、更宽松。

unsigned short*指向内存中包含类型为unsigned short的对象的位置。 该内存位置不包含unsigned int类型的对象。 当指向的位置不存在该类型的对象时,通过指向该类型的指针进行间接访问的行为通常是未定义的(某些类型有例外)。

您不能将指针转换为另一种指针类型并期望它起作用。 指针指向 unsigned short 的内存位置。
如果您需要转换,那么您必须将未签名的 short 从内存中拉出并将其放入另一个内存中。

// in main
unsigned short *ptr_a = something(); // something return me a unsigned short *a

unsigned int b = static_cast<unsigned int>(*ptr_a); // cast the object at a into an uint
unsigned int ptr_b = b&; // get the address for the new object

std::cout << *ptr_a << std::endl;
std::cout << *ptr_b  << std::endl;

但是,当您从函数返回指针时,您不能使用堆栈上对象的地址(如本例中的 b&),而是需要使用new 在这种情况下,您应该确保您也调用了delete

int* something() {
    // int a = 5;
    // BAD - DON'T DO THIS: return a&;
    int* a = new int;
    *a = 5;
    return a; // OK, but remember to delete
}

// in some function, eg. main
unsigned short *ptr_a = something(); // something return me a unsigned short *a

unsigned int *ptr_b = new int;
*ptr_b = static_cast<unsigned int>(*ptr_a);

std::cout << *ptr_a << std::endl;
std::cout << *ptr_b  << std::endl;
delete ptr_a;
delete ptr_b;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM