2015-04-20 64 views
3

我有一些字節字段包含不同數值類型的字段。指向這些字段的指針然後傳遞並作爲其他類中的成員存儲。在C++中使用char *或void *或其他字節字段?

我應該使用char*還是void*作爲指針類型?

目前,我看到char*只有一個優勢:您不能取消void*。從字段中讀取值時,這不是問題,因爲我必須將其轉換爲相應的指針類型。如果我想逐字節地複製一個字段,我首先需要將void*轉換爲char*,所以將其直接存儲爲char*會更容易。

還是有什麼理由反對使用char*

通常,我寧願保持儘可能低的水平,因爲我必須將字段傳遞給其他低級別接口。

+0

你如何編碼有什麼指針背後,像接聽其不同的數值類型之一是這個指針指向? – Jojje

+0

它應該主要取決於你的擔心,如果你喜歡把內存視爲不透明的,void *會阻止你意外解引用,如果你喜歡對內存進行編碼/解碼,可以使用語義數據類型,如char *','unsigned int *'等是首選。 –

+0

@Jojje:這種情況發生的方式有很多種。例如,該字段發送給一個總是期望雙倍的函數。但通常這個問題不應該發揮作用。 – Michael

回答

5

對內存blob使用char *是「易於使用」(e.b.逐字節操作),但它對於閱讀和理解代碼是非常不利的(但您仍然可以在各種API中看到它)。

如果你的數據只是一塊內存,那麼最好使用void *。

僅當您的數據是特定類型的數組(char,int,uint8_t,某個struct,...)時,才使用該類型的指針。如果你需要把一個結構看作「字節數據」(例如計算一個散列),你可以在內部把它當作「char *」(或者uint8_t *或者uint_32_t *或者你需要的任何東西)。然而,如果你不需要特定的內存佈局,公共API應該仍然是無效的*。問題是:如果你有一個使用void *的API,你可以提供任何類型的指針(它是散列函數的一個指針)。但是,如果使用char *,則始終需要reinterpret_cast。

2

使用char會引發一些問題 - 這完全取決於您想如何處理存儲在這些指針後面的值。

問題是,byte通常被解釋爲無符號值。例如:UTF-8編碼。它產生字節序列,that can have different values, depending on encoded code point。如果我們使用帶符號的類型,則必須將值轉換爲無符號類型以便能夠正確檢查其值(大於U+007F的代碼點總是轉換爲字節序列,其中所有字符都將符號位設置爲1)。

但是,char是否被簽名是依賴於實現的。事實上,C++標準定義了三種不同的類型:

  • 焦炭
  • 符號字符
  • 無符號的字符

如果包括#include <limits.h>,你可以看看CHAR_MIN

  • 如果定義爲0,則char無符號
  • 如果定義爲一些負面的值(通常爲-128),焦炭簽署

那麼,這一切意味着什麼?

您應該以某種方式存儲字節,這將允許您讀取/寫入它們的值而無需額外的檢查。你可能希望你的字節是一個無符號值,所以定義新的類型(如manyhigh-levellanguages做):

typedef unsigned char Byte; 

,然後定義指針爲:,

Byte* data_pointer; 

那麼如果你的函數期望'void *'或'Byte *',不需要做任何事情。但是,如果他們期望指向特定數字類型的指針(int,float等),則需要reinterpret_cast這些指針。

+0

在使用它們之前,我總是將字節字段中的值轉換爲明確定義的數據類型。 W計劃只在傳遞程序中的字節字段時使用char *或void *。那麼這個答案是否與這個問題相對應? – Michael

+0

是的。您無論如何都需要投射這些指針,但將它們定義爲指向「Byte」的指針,可讓您輕鬆便攜地使用它們,如果您在某些時候決定某個函數應該使用像字節序列這樣的指針來執行逐字節字節操作。這與您在問題中提到的原因完全相同,但使用便攜式類型,在所有平臺上的行爲相同,都是更好的解決方案。 –

0

資源非常簡單和低是一個簡單的鍵入指針的聯合,因爲我的理解實際類型是通過上下文,這使得它很適合。

要在另一端運行時動態有 Boost::Any

相關問題