我來自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