C Bit Field 使用注意事項

C Bit Field 在存取暫存器的欄位是非常好用的,例如



我定義一個 Union 如下:

 union CacheParameters {
  struct {
   enCacheType byCacheType : 5;
   BYTE byCacheLevel : 3;
   BOOL bSelfInitializing : 1;
   BOOL bFullyAssociativeCache : 1;
   BYTE : 4;
   WORD wMaximumNumberOfThreadsSharingThisCache : 12;
   BYTE byMaximumNumberOfProcessorCoresInThisPhysicalProcessorPackage : 6;

   WORD wSystemCoherencyLineSize : 12;
   WORD wPhysicalLinePartitions : 10;
   WORD wWaysOfAssociativity : 10;

   DWORD dwNumberOfSets : 32;

   BOOL bWBINVD_INVD_BehaviorOnLowerLevelCaches : 1;
   BOOL bCacheIsInclusiveToLowerCacheLevels : 1;
   BOOL bComplexCacheIndexing : 1;
   DWORD : 29;
  } fields;
  struct {
   DWORD eax;
   DWORD ebx;
   DWORD ecx;
   DWORD edx;
  } registers;
 };

很合理吧,根據每個欄位的長度定義資料型態,結果很慘,讀回來的資料沒錯,但對應到欄位時完全不對。

後來參考 msdn C Bit Fields 才知道欄位的型態宣告只能用 unsigned int, signed int or int,所以我的 union 修改如下就一切正常了。

 union CacheParameters {
  struct {
   DWORD byCacheType : 5;
   DWORD byCacheLevel : 3;
   DWORD bSelfInitializing : 1;
   DWORD bFullyAssociativeCache : 1;
   DWORD : 4;
   DWORD wMaximumNumberOfThreadsSharingThisCache : 12;
   DWORD byMaximumNumberOfProcessorCoresInThisPhysicalProcessorPackage : 6;

   DWORD wSystemCoherencyLineSize : 12;
   DWORD wPhysicalLinePartitions : 10;
   DWORD wWaysOfAssociativity : 10;

   DWORD dwNumberOfSets : 32;

   DWORD bWBINVD_INVD_BehaviorOnLowerLevelCaches : 1;
   DWORD bCacheIsInclusiveToLowerCacheLevels : 1;
   DWORD bComplexCacheIndexing : 1;
   DWORD : 29;
  } fields;
  struct {
   DWORD eax;
   DWORD ebx;
   DWORD ecx;
   DWORD edx;
  } registers;
 };

PS:
  1. Reserved 的欄位可以不設定欄位名稱,這樣在程式中就不會參考到了
  2. 原本以為欄位總長度不能超過 32 bits,沒想到也一併解決了!

留言

這個網誌中的熱門文章

Linux 批次檔的寫法

【分享】如何顯示 Debug Message

[分享] Visual Studio 遠端偵錯