對 void* 做偏移,你會得到編譯器的一個 warning


標準 C/C++ 不支持 void* 上的加減法,不過 gcc 上有擴展(+1):

Pointer Arith (Using the GNU Compiler Collection (GCC))?

gcc.gnu.org

6.24 Arithmetic on void- and Function-Pointers

In GNU C, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1.A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.The option -Wpointer-arith requests a warning if these extensions are used.


其實內存分配中常見的是void**的偏移


在大部分編譯器裏,對void指針不支持arithmetic operation(算術運算)。如果你這樣做了,會得到一個編譯錯誤。

但GCC/G++除外,具體可參考GCC文檔6.23。

In GNU C, addition and subtraction operations are supported on pointers tovoidand on pointers to functions. This is done by treating the size of avoidor of a function as 1.

GCC會把void*當作一個位元組來處理,偏移量也是一個位元組。這個特徵是GCC對ISO CPP的擴展,並不是C++本身的語言特性。

PS. 個人一直覺得GCC這個設定並不合理,在不確定變數長度的情況下盲目做數據讀寫很危險。


指針即地址變數。

地址二要素:地址值、地址處對象大小

後者決定了對地址加一之後,得到的地址值。

int*指針的「地址處對象大小」為4。

而void*指針裏的地址,不具備地址二要素的第二要素。對它談加一是沒有意義的。


或者,你可以認為c語言裏的地址分為兩類:

有類型的地址(除void*外的所有地址類型)

無類型的地址(void*)


void*指針不能偏移。


理論上 void * 不能偏移

實際上

gcc 會偏移一個地址

clang 編譯不過


你用void*加1的話,編譯器會報錯,提示你要給個類型


問題本身就是錯的

int*指針偏移一次4個地址

在int類型需要佔用四個地址的編譯器裏,int指針的步長纔是4。


void*要用就一定要轉。不知道類型編譯器怎麼給你偏移呢。要不然就是警告 要不然就編譯不過。其實這種問題沒必要多想啦


void指針不偏移,一般作為一般指針傳入(說白了就是傳一個指針變數的值)。用的時候強轉你想要的類型指針就是了。


按照國內C90標準GB/T 15272-94 ,指向void類型的指針應與指向字元類型的指針具有相同的表示和對齊要求。


你先自己試試嘛,這好像算ub了吧,不允許對void類型指針做偏移改動啊


不管參見什麼文檔,都比不上自己測試來得直接

#include "stdio.h"

int main(void)
{
char a = a;
int b = 1;

char *pstr = a;
int * pint = b;

void *pvoid = NULL;

printf("%p %p
",pstr,pstr+1);
printf("%p %p
",pint,pint+1);

pvoid = b;
printf("%p %p
",pvoid,pvoid+1);
pvoid = a;
printf("%p %p
",pvoid,pvoid+1);
getchar();
return 0;
}

代碼輸出

000000000062FE07 000000000062FE08
000000000062FE00 000000000062FE04
000000000062FE00 000000000062FE01
000000000062FE07 000000000062FE08

我使用的是devc++

編譯~


void 並不表示無類型或空類型的意思,參見《C++程序設計精要教程》,它表示類型不知道,隨便什麼類型都可以。因此void *表示指向任何類型(故任何位元組數的內存塊)均可。由於指針指向的位元組數不定,故指針移動一次跳過多少位元組不定,故不允許void*p之類的指針p移動,如p+1、p++、p=p+1以及*(p+1)。void *p可以接受許多(不是任何)具體類型的指針或地址的值,例如p=new int [6]; p=new double[6]; 等。但delete的參數為const void*類型,以便接受任何類型(歷史原因:這裡是任何。不用許多一詞)的指針或地址。而要在catch的捕獲列表接受任何指針類型的實參,須用const volatile void *。類型解析是C或C++的難點,還是看前述教程吧。太多內容,一言難盡。


gcc親測偏移一位元組,不過會warning。


推薦閱讀:
相關文章