2012-06-19 56 views
5

我的問題是關於指向奇數大小的內存塊。特定位大小的C++指針

比方說,我有聲明,像這樣一個struct

typedef struct{ 
    int32 val1 : 29; 
    int32 val2 : 26; 
    char val3; 
}MyStruct; 

假設聲明特定位字段的結構是desireable(爲什麼我們會使用位域不是問題)。

如果我想聲明的是指向這些領域的一個指針,我可能會嘗試這樣的事:

MyStruct test; 
int32 *myPtr = &(test.val1); 

除此產生錯誤「走位域的地址不允許「。

假設我們想要,有沒有辦法以這種方式指向這些字段?我知道C++可能會將字段填充到下一個字節(在這種情況下將是32位)。

+3

由於指針指向字節,因此我認爲這種行爲是正常的,因爲沒有辦法存儲可能不是「完整」字節的地址。 – ereOn

+1

我不相信你會看到指定位大小的位域成員的任何填充(或者至少,你不能確定是否有任何 - 是實現定義的)。 – RichieHindle

+0

@RichieHindle:的確,對於大多數小值,不會有填充,因爲這正是發明位域的原因。 – PlasmaHH

回答

11

在C++中,最小的可尋址值的大小必須至少爲1個字節。所以不,你不能使用指針來獲取位域的地址。

C++ 03標準9.6位字段:
第3段:

...操作&地址,不得應用於位字段,所以有沒有指向位域的指針。 ....

6

除此產生錯誤「走位字段的地址是不允許的」。

這是標準明確禁止的。見[class.bit] 9.6/3:

操作者&地址-不得被應用到一個位域,所以沒有指針位字段。

一個字節(它是CHAR_BIT位寬,其中CHAR_BIT是至少8)是可以解決最小。

假設我們想要,有沒有辦法以這種方式指向這些字段?

不,你可以有一個指向封閉struct類型的對象的指針。這是C的直接結轉;見C FAQ 2.26

位字段不便時,您還希望能夠操縱位的某一集作爲一個整體(也許是爲了複製一組標誌)。

你可能想看看其他的替代品std::bitsetboost::dynamic_bitset

0

無法獲取指向位字段的指針。如果你願意自己實現一個等效的結構,然而,使用shift和 掩碼,你應該能夠定義一個智能指針。東西 這樣的:

class BitFieldPointer 
{ 
    unsigned* myData; 
    unsigned myMask; 
    unsigned myShift; 

    class DereferenceProxy 
    { 
     BitFieldPointer const* myOwner; 
    public: 
     DereferenceProxy(BitFieldPointer const* owner) : myOwner(owner) {} operator unsigned() const 
     { 
      return (*myOwner->myData && myOwner->myMask) >> myOwner->myShift; 
     } 

     void operator=(unsigned new_value) const 
     { 
      *myData = (*myOwner->myData && ~myOwner->myMask) | 
        ((new_value << myOwner->myShift) && myOwner->myMask); 
     } 
    }; 
public: 
    // ... 
    DereferenceProxy operator*() const 
    { 
     return DereferenceProxy(this); 
    } 
}; 

(這只是一個粗略的想法,您可能會想這兩個指針和 指針常量,並且代理與它的主人 的壽命可能是一個。問題。)