何时以及如何允许转换为字符指针
When and how is conversion to char pointer allowed?
我们可以通过将指向该对象的T*
转换为char*
来查看T
该对象的表示形式。至少在实践中:
int x = 511;
unsigned char* cp = (unsigned char*)&x;
std::cout << std::hex << std::setfill('0');
for (int i = 0; i < sizeof(int); i++) {
std::cout << std::setw(2) << (int)cp[i] << ' ';
}
这将在我的系统上输出511
的表示形式:ff 01 00 00
。
这里(肯定)发生了一些实现定义的行为。哪些演员允许我将int*
转换为unsigned char*
,该转换需要哪些转换?我是否在投掷后立即调用未定义的行为?我可以像这样投射任何T*
类型吗?这样做时我可以依靠什么?
哪个演员允许我将
int*
转换为unsigned char*
?
在这种情况下,C型转换与reinterpret_cast<unsigned char*>
相同。
我可以像这样铸造任何 T* 类型吗?
是和不是。yes 部分:可以安全地将任何指针类型转换为char*
或unsigned char*
(使用适当的const
和/或volatile
限定符)。结果是实现定义的,但它是合法的。
no 部分:该标准明确允许char*
和unsigned char*
作为目标类型。但是,您不能(例如)安全地将double*
转换为int*
。这样做,你就跨越了从实现定义的行为到未定义行为的边界。它违反了严格的别名规则。
您的演员表映射到:
unsigned char* cp = reinterpret_cast<unsigned char*>(&x);
int
的基础表示形式是实现定义的,将其视为字符可以检查这一点。 在您的情况下,它是 32 位小端序。
这里没有什么特别之处 - 这种检查内部表示的方法对任何数据类型都有效。
C++03 5.2.10.7:指向对象的指针可以显式转换为指向不同类型的对象的指针。 除了将类型为"指向 T1 的指针"的右值转换为"指向 T2 的指针"类型(其中 T1 和 T2 是对象类型,T2 的对齐要求不比 T1 的对齐要求更严格)并转换回其原始类型会生成原始指针值之外,未指定此类指针转换的结果。
这表明强制转换会导致未指定的行为。 但实际上,从任何指针类型转换为char*
将始终允许您检查(和修改)引用对象的内部表示形式。
在这种情况下,C 样式的强制转换等效于 reinterpret_cast。该标准描述了 5.2.10 中的语义。具体而言,在第7段中:
"指向对象的指针可以显式转换为指向 不同的对象类型.70 当类型为"指向 T1 的指针"的 prvalue v 为 转换为类型"指向 cvT2 的指针",结果为
static_cast<cvT2*>(static_cast<cvvoid*>(v))
T1 和 T2 是否 标准布局类型 (3.9) 和 T2 的对齐要求是 不比T1严格。将类型为 "指针到 T1"到类型"指向 T2 的指针"(其中 T1 和 T2 是对象类型,并且 T2的对准要求不比T2更严格 T1) 并返回到其原始类型将生成原始指针值。 任何其他此类指针转换的结果都是未指定的。
在您的情况下,这意味着什么,满足对齐要求,并且未指定结果。
示例中的实现行为是系统的字节序属性,在本例中,CPU 有点字节序。
关于类型转换,当您强制转换int*
以char*
您正在执行的所有操作时,告诉编译器将cp
指向的内容解释为 char,因此它将仅读取第一个字节并将其解释为字符。
指针之间的强制转换本身总是可能的,因为所有指针都只不过是内存地址,并且内存中的任何类型都可以始终被视为字节序列。
但是 - 当然 - 序列的形成方式取决于分解类型在内存中的表示方式,这超出了C++规范的范围。
也就是说,除非是非常病态的情况,否则您可以期望同一编译器为同一平台(或系列)的所有机器生成的所有代码上的表示形式是相同的,并且您不应该期望在不同平台上获得相同的结果。
一般来说,要避免的一件事是将类型大小之间的关系表示为"预定义": 在您的样本中,您假设sizeof(int) == 4*sizeof(char)
:这不一定总是正确的。
但是 sizeof(T) = N*sizeof(char) 总是正确的,因此无论 T 如何,都可以始终被视为 char-s 的整数
除非你有一个强制转换运算符,否则强制转换只是告诉以不同的方式"看到"该内存区域。没什么特别的,我会说。
然后,您正在逐字节读取内存区域;只要您不更改它,它就可以了。当然,您看到的结果在很大程度上取决于平台:考虑字节序、字大小、填充等。
只需反转字节顺序,然后它就变成了
00 00 01 ff
即 256 (01) + 255 (ff) = 511
这是因为您的平台是小端序。
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 如何循环访问 cpp 中的函数返回的字符指针数组
- 将(N 个字节)无符号字符指针转换为浮点数和双 C++
- 字符指针的 Qt 数组
- C++将常量字符* 指针数组传递给对象
- 为什么不能将字符指针定义为数组?
- 在函数内初始化无符号字符指针将返回空指针
- 将字符指针存储到容器中
- 为什么 strtok_r() 只接受字符数组而不接受字符指针
- 字符指针数组内存分配
- 字符指针不递增?
- 如何在C++中使用字符指针
- 确保字符指针始终指向相同的字符串文字
- C++中的字符指针
- 使用unique_ptr的常量字符指针
- 字符指针不断意外更改
- 将字符指针中的十六进制转换为十进制
- 如何将字符*(字符指针)转换为 PCSZ?
- 在向量中存储字符指针
- 字符指针具有不同的值