2012-07-29 109 views
1

我來自C#和Java的背景,我似乎無法理解C++中使用指針進行投射的含義。C++類型使用指針投射

例如:

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

它有什麼作用?它對於什麼有用?

+4

在C++中,你應該避免強制轉換。投射是告訴編譯器「不,不,你會認爲這是錯誤的,但我確定我是對的」。在C++中,儘管總是讓編譯器正確無誤。投射是一種抑制編譯器錯誤的方法。所以基本上,爲了某個特定目的而要求鑄造,而不是一般鑄造,這是更具建設性的。你的兩個例子都應該在C++中完全避免。 – tenfour 2012-07-29 10:55:19

+0

你想知道如何使用指針來轉換或者從你的例子中轉換爲char *和char const嗎? – Rndm 2012-07-29 11:00:33

+0

我編輯了這篇文章,現在應該更清楚我的想法。 – UnTraDe 2012-07-29 11:00:55

回答

4

在這兩個例子中,你都犯了錯誤,導致代碼不能編譯。所以我會假設你想做到以下幾點:

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();" 
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 

有你需要做的這個非常幾次。

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; 
... 
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 

標準說,它是未定義的行爲通過指針是正確的類型(也稱爲「雙關型」)的未訪問的對象。雖然它是確定的存儲對象的指針,也就是說,一個void*,然後再轉換回來,並使用它,它是確定治療浮動,就好像它是一個整數,等的唯一接受的方式訪問一個對象就好像它是另一個對象一樣,就是我所演示的一個對象,即將T類型的對象看作是一個數組char[sizeof(T)] —,也就是說,您可以訪問每個對象的基礎二進制表示。