程式在移植或者整合時, 有時會遇到使用結構來的定義程式所用到的資料的情形, 有時原作者是用一指向結構的指標來處理, 但是有時也會有直接用結構變數的情形.

這些程式我們在使用的時候按理應該盡量不要更動以免日後改版時造成問題, 不過要是遇到下面二種狀況那就...

  1. 原始程式是用指標來指向要處理的結構變數, 而現在我們想把規模縮小, 只會有一份結構變數, 同時也希望最佳化目的碼, 讓系統小一點, 快一點.
  2. 或者原始程式中把結構變數寫死了, 所有的函數都是針對那一個結構變數寫的, 結構變數生不出第二個 instance 來. 而我們卻是需要擴充一下, 讓它能處理多個結構變數.

第一個情況容易一些, 只要把 struct_ptr->member 的寫法改成 struct_var.member 就好了, 不會有負作用.

第二個情況除了把寫法倒過來改 (struct_var.member 改成 struct_ptr->member), 還要檢查是否有其他問題, 例如: 是否需要支援多執行緒, 函數是否可以 reentry...

我們暫且把它單純化, 在這裡只看 struct_ptr->memberstruct_var.member 互轉的問題.


個人在移值的試驗過程中, 發現使用巨集定義可以在不動用編輯器全面的置換修改原始程式而在編譯時將運算式中的寫法予以修正. 這點可以符合原始程式盡量不要更動的精神. 但是宣告的部份卻無法順利置換, 因此需要另外修改宣告的部份.

要將原本用指標的程式改成使用結構變數時, 只需將指標變數的宣告稍加修改, 並在宣告行之下加入下列一行巨集定義來置換即可

#define Struct_Ptr      (&Struct_Var)

反之, 要將原本用結構變數的程式改成使用指標時, 只需在結構變數的宣告行稍加修改, 並在宣告行之下加入下列一行巨集定義來置換

#define Struct_Var      (*Struct_Ptr)

上面的二個式子中:

  • Struct_Ptr 是指標變數
  • Struct_Var 是結構變數
  • 第一個式子是使用指標變數的原程式轉成使用結構變數
  • 第二個式子是使用結構變數的原程式轉成使用指標變數

下面是修改的例子: 修改前

struct _LIST {
    struct _LIST *pNext;
    uint16_t      size;
    ...
} freeList;

x = freeList.pNext;
freeList.size = y;

修改後:

struct _LIST {
    struct _LIST *pNext;
    uint16_t      size;
    ...
//} freeList;    // 把結構變數宣告
} *pFree;        // 改宣告為指標
#define freeList    (*pFree)   // 插入這一行

x = freeList.pNext;
freeList.size = y;

轉換解說:

  • 首先把原始程式中 freeList.pNext 先以我們新加入的定義置換 freeList, 置換後變成了 (*pFree).pNext
  • 接著再將 (*p).x 寫法換成另一種對等寫法 p->x, 所以變成了 pFree->pNext
  • 所以 freeList.size 也就轉換變成了 pFree->size

例二: 修改前

struct _LIST {
    struct _LIST *pNext;
    uint16_t      size;
    ...
};
struct _LIST *ptr;

x = ptr->pNext;
ptr->size = y;

修改後:

struct _LIST {
    struct _LIST *pNext;
    uint16_t      size;
    ...
};
//struct _LIST *ptr;   // 把結構指標宣告,
struct _LIST flist;    // 改宣告為結構變數
#define ptr     (&flist)   // 插入這一行

x = ptr->pNext;
ptr->size = y;

轉換解說:

  • 首先將 p->x 寫法換成另一種對等寫法 (*p).x, 於是 ptr->pNext 變成 (*ptr).pNext
  • 再以我們新加入的定義置換 ptr, 置換後變成了 (*(&flist)).pNext, *(&flist) 取址再取值可以相互抵消, 於是變成了 flist.pNext
  • 或者說 ptr 相當於 &flist, 所以 *ptr 也就相當於 flist, 因此 (*ptr).pNext 就相當於 flist.pNext
  • 一樣的 ptr->size 就轉換成了 flist.size


其他相關文章:

    MagicJackTing 發表在 痞客邦 留言(0) 人氣()