4

我来自 C# 和 Java 的背景,我似乎无法理解在 C++ 中使用指针进行强制转换意味着什么。

例如:

int x = 1;
char c = *((char*)&x);

它有什么作用?它有什么用?

4

5 回答 5

6

在您的两个示例中,您都犯了错误,导致代码无法编译。因此,我假设您正在尝试执行以下操作:

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();"
于 2012-07-29T11:05:17.017 回答
4

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

您需要执行此操作的次数很少。

于 2012-07-29T11:04:36.337 回答
2

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)]——也就是说,你可以访问每个对象的底层二进制表示。

于 2012-07-29T11:44:27.837 回答
1

你应该尽量避免像 (char*) 这样的 c 类型转换。如果您真的需要进行类型转换,请查看dynamic_cast,static_castreinterpret_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

于 2012-07-29T11:06:06.450 回答
1

很多年前,我使用该习惯用法在自定义 IO 板上的指定地址访问硬件。因此,例如在 PIC(可编程中断控制器)上写入以重置某些标志(虚构代码):

#define PIC_LOC 0x1000
#define PIC_ENABLE_PORT *((char*)(PIC_LOC+0x10))
#define BIT_ENABLE (1 << 3)

...
PIC_ENABLE_PORT |= BIT_ENABLE;
...
于 2012-07-29T11:11:17.593 回答