簡體   English   中英

將void *指針強制轉換為char *指針並在其上執行指針算術是一種有效的操作嗎?

[英]Is it a valid operation to cast a void* pointer to char* pointer and doing pointer arithmetics on it?

我有一個指向內存中malloc的塊/數組的指針(void *),我知道存儲在該塊中的數據結構的大小。 我希望能夠遍歷塊以訪問任何單個值。

程序知道:

  • void *指針將指向這個malloc的內存塊的開始。

  • 每個值的大小[以字節為單位],但不是實際存儲的數據結構。

  • 容量[以字節為單位]:這些值的潛在數量(分配了多少內存)

這意味着我有malloc'ed:Capacity * Size_of_value字節,我想得到一個指向該塊內任何值的指針,通過:

  1. 將void *指針轉換為char *指針。

  2. 將所需的Size_of_value倍數添加到char *指針:從而獲得指向任何所需值的指針。

我學到的是,將N添加到char *指針,使其向前移動N個字節。 而且我知道指針必須以[amount]字節向前移動,我可以將[amount]添加到此char *指針。

我找不到合適的來源,通常只能確定不允許在虛空*上使用算術。

從我到目前為止的攻擊,它似乎正常工作,只要存儲的結構具有恆定的已知大小。 結構中的靈活數組成員會破壞我當前的實現。 這是我打算通過創建擴展來修復的缺點:列表將保存指向指針數組的指針,這些指針將提供對實際值的訪問。


可能有用也可能沒用的上下文:

我正在研究列表數據結構的實現,我實現它基本上是一個動態數組(在需要時擴展和收縮),具有更多接口。

我知道鏈接列表,我也計划將它們作為一個不同的練習來實現。

我像這樣定義了這個列表:

typedef struct TLIST_
{
    size_t size_of_value;      // size [in bytes] of each record stored in the list
    size_t list_capacity;      // memory has been allocated for this many values(size can't be larger than this)

    size_t list_size;          // number of stored records 
    void* pointer_to_zero;     // address of the content
} tlist;

// The list has a few other values for various options and operations(e.g.: disallowing it to expand automatically, displaying the content), but those four values is all that's needed for this problem.

獲取指向給定索引值的指針的函數:

void* tehlist_generic_getPointerToIndex(const tlist* list__, const int index__) 
{
    const int capacity =  (*list__).list_capacity;
    if( index__ >= 0 && index__ < capacity )
    {
        // Move pointer forward by a given amount of bytes, through casting the void* to a char*
        // 1. Can't do pointer arithmetic on void*, but can on char*
        // 2. char* is defined as 1[unit or byte],
        // thus moving char* forward by N, causes it to move as if we were moving through a pointer that was of size N

        void* pointer_to_index = (*list__).pointer_to_zero;

        const size_t bytes_forward = (*list__).size_of_value*index__;
        pointer_to_index = (char*)(pointer_to_index) + ( bytes_forward );

        return pointer_to_index;
    }
    return 0;
}

我發現的其他信息:

GNU C編譯器提供了一個C語言擴展,允許對void*進行算術運算,將其視為大小為1(就像它被轉換為char* ):

https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith

這在ISO C中是不允許的,僅在GNU C中。

是的,轉換為char *始終是合法的,取消引用該指針僅在分配的塊的范圍內是合法的。

C99標准在6.3.2.3中說:

指向void的指針可以轉換為指向任何不完整或對象類型的指針。 指向任何不完整或對象類型的指針可能會轉換為指向void的指針並再次返回; 結果應該等於原始指針。

所以,只要你使用實際類型的指針(在本例中為char *)進行算術運算,它就完全有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM