我来自C#和Java的背景,我似乎无法理解C++中使用指针进行投射的含义。C++类型使用指针投射
例如:
int x = 1;
char c = *((char*)&x);
它有什么作用?它对于什么有用?
我来自C#和Java的背景,我似乎无法理解C++中使用指针进行投射的含义。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型蒙上样(字符*)通过各种手段。如果你真的需要做一个类型演员,请看dynamic_cast
,static_cast
和reinterpret_cast
。
但如前所述,你很少需要铸造。
看看这里的fruther信息: 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;
...
有在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
标准说,它是未定义的行为通过指针是正确的类型(也称为“双关型”)的未访问的对象。虽然它是确定的存储对象的指针,也就是说,一个void*
,然后再转换回来,并使用它,它是不确定治疗浮动,就好像它是一个整数,等的唯一接受的方式访问一个对象就好像它是另一个对象一样,就是我所演示的一个对象,即将T
类型的对象看作是一个数组char[sizeof(T)]
—,也就是说,您可以访问每个对象的基础二进制表示。
在C++中,你应该避免强制转换。投射是告诉编译器“不,不,你会认为这是错误的,但我确定我是对的”。在C++中,尽管总是让编译器正确无误。投射是一种抑制编译器错误的方法。所以基本上,为了某个特定目的而要求铸造,而不是一般铸造,这是更具建设性的。你的两个例子都应该在C++中完全避免。 – tenfour 2012-07-29 10:55:19
你想知道如何使用指针来转换或者从你的例子中转换为char *和char const吗? – Rndm 2012-07-29 11:00:33
我编辑了这篇文章,现在应该更清楚我的想法。 – UnTraDe 2012-07-29 11:00:55