我来自 C# 和 Java 的背景,我似乎无法理解在 C++ 中使用指针进行强制转换意味着什么。
例如:
int x = 1;
char c = *((char*)&x);
它有什么作用?它有什么用?
在您的两个示例中,您都犯了错误,导致代码无法编译。因此,我假设您正在尝试执行以下操作:
int x = 1;
char c = *((char*)&x);
根据您的体系结构,c
现在将具有x
. 在此示例中,这将是 0 或 1(这实际上可以用于检测字节顺序)。
您的第二个示例不起作用,因为您试图忽略const
导致非法操作/错误转换的结果(这也称为“const 正确性”)。
编辑:关于您对“这是什么意思?”的评论:
在表达式中:
&somevariable
将返回 的地址somevariable
。
*somevariable
将假定 的内容somevariable
是实际值的地址,然后返回。
在声明中:
datatype
是一个普通的变量/对象。这是“按值”传递的。
datatype&
是参考。这与 Java/C# 中的普通变量完全一样,并且通过引用传递。
datatype*
是一个指针。这仅包含实际值所在的地址(见上文),并且本质上也是通过引用传递的。
实际转换的工作方式与 Java/C# 非常相似,但指针就是这样:它们指向实际值的位置。虽然这可能会让您感到困惑,但 C/C++ 中的指针的工作方式与 Java/C# 中使用的标准变量/引用非常相似。
看这个:
MyClass x; // object of MyClass
MyClass *x; // pointer to an object of MyClass - the actual value is undefined and trying to access it will most likely result in an access violation (due to reading somewhere random).
MyClass *x = 0; // same as above, but now the default value is defined and you're able to detect whether it's been set (accessing it would essentially be a "null reference exception"; but it's actually a null pointer).
MyClass &x = MyClass(); // creating a new reference pointing to an existing object. This would be Java's "MyClass x = new MyClass();"
C++ 中的强制转换就像 Java 中的强制转换一样,不涉及指针。
int x = 1;
char c = (char) x; // Lose precision
但是,你在这里做什么:
int x = 1;
char *c = (char *)x;
告诉编译器的值x
是一个字符的地址。它相当于
char *c;
c = 1; // Set the address of c to 0x0000000000000001
您需要执行此操作的次数很少。
C++ 中有两个根本不同的概念,它们有时都被称为“转换”:一个是转换,一个是重新解释。
转换会创建一个与现有对象具有“相同值”但类型不同的新对象。这里有些例子:
示例 1:类型提升
// 1a: promote int to double to get the correct type of division
int numerator = rand(), denominator = rand();
double d = double(numerator) / double(denominator);
// 1b: convert int to double to achieve a particular argument deduction
int n;
template <typename T> void do_numeric_stuff(T x) { /* ... */ }
do_numeric_stuff(double(n));
示例 2:派生到基础的转换
struct B { }; struct D : B { };
D x;
D * p = &x; // pointer to x
B * q = p; // implicit conversion; may change the value!
另一方面,重新解释允许我们将一个变量视为另一个变量。关于此的唯一正确和有用的应用程序是序列化,以一种或另一种形式。
示例 3:序列化
std::ofstream file("output.bin"); // output file
char large_buffer[HUGE]; // in-memory buffer
unsigned int n = get_data();
char const * p = reinterpret_cast<char const *>(&n);
file.write(p, p + sizeof n); // write the bytes of `n`
std::copy(p, p + sizeof n, large_buffer); // ditto
std::copy(large_buffer + 17, large_buffer + 17 + sizeof n,
reinterpret_cast<char *>(&n)); // repopulate `n` from buffer
该标准表示,通过不正确类型的指针访问对象是未定义的行为(也称为“类型双关语”)。虽然可以将对象指针存储在 a 中void*
,然后将其转换回并使用它,但不能将浮点数视为整数等。访问一个对象的唯一可接受的方式是另一种是我演示的,即将一个类型的对象T
当作一个数组来处理char[sizeof(T)]
——也就是说,你可以访问每个对象的底层二进制表示。
你应该尽量避免像 (char*) 这样的 c 类型转换。如果您真的需要进行类型转换,请查看dynamic_cast
,static_cast
和reinterpret_cast
.
但如前所述,您几乎不需要演员阵容。
在这里查看更多信息: http ://www.cplusplus.com/doc/tutorial/typecasting/
http://www.parashift.com/c++-faq/static-typing-and-cpp.html
http://www.parashift.com/c++-faq-lite/print-char-or-ptr-as-number.html
很多年前,我使用该习惯用法在自定义 IO 板上的指定地址访问硬件。因此,例如在 PIC(可编程中断控制器)上写入以重置某些标志(虚构代码):
#define PIC_LOC 0x1000
#define PIC_ENABLE_PORT *((char*)(PIC_LOC+0x10))
#define BIT_ENABLE (1 << 3)
...
PIC_ENABLE_PORT |= BIT_ENABLE;
...