[英]Why can't we generalize the pointer declaration?
無論指向的數據類型如何,指針的大小都是相同的。那為什么我們需要聲明它指向的數據類型?
例如,
int *p; //p will point to an integer data type.
char *p; //p will point to a character
那么,為什么我們不能概括這樣的指針聲明
pointer p; //where p is an object of pointer class.
TL; DR因為,不同的數據類型在內存中占用不同的大小並且具有不同的對齊要求。
詳細說明,指針變量包含指向某種類型數據的地址。 如果沒有關聯的類型,就無法取消引用指針並獲取值 。
換句話說,要訪問指針指向的數據,必須知道關聯的數據類型。
指針本身的大小與它指向的實際數據幾乎沒有聯系。
存在一個指針, void *
被認為是一個通用指針,但是,你不能取消引用它,因為取消引用的結果會嘗試產生一個不完整的類型。 您需要將其強制轉換為完整類型,以便能夠取消引用或對void指針應用指針算法。
考慮void *
一般指針的原因如下,引用C11
標准,第6.3.2.3章
指向
void
的指針可以轉換為指向任何對象類型的指針。 指向任何對象類型的指針可以轉換為指向void
的指針,然后再返回; 結果應該等於原始指針。
因此, void *
可以用作可以保存任何指針類型的通用容器 ,但是要對指針進行一些操作(包括數據類型的知識),首先需要將其轉換為完整類型。
指針算術。
說明:
int arr[] = {4, 6, 9, 10};
int* x = arr;
*(x+0) = 4
*(x+1) = 6
編譯器知道x + 1實際上是x + sizeof(int)而不是1。
要讀取第二個元素,編譯器必須每次都跳過sizeof(int)。 在不知道實際類型的情況下,您無法取消引用它並正確提取數據。
Plus類型的大小不同,編譯器需要知道從指向的內存中讀取多少字節。 char將是1個字節,int將超過1個字節。
您可以使用void*
來概括指針。 void*
是指向某個地址的指針,沒有任何關聯的類型信息。 但是,如果不將這些指針首先強制轉換為顯式指針類型,則幾乎無法使用這些指針。
請考慮以下示例。 它不會編譯,因為不可能推斷出ptr
指向的“值”。 你甚至不知道該值構成了多少字節。
void print(const void * ptr) {
std::cout << *ptr; // What's the "value" of ptr?
}
void *
指針可以被視為“通用”指針。
但是,它不能被解除引用,因為通用它並不指向任何一種類型的對象。 要實際使用 void *
指針並訪問它指向的任何內容,您需要將其強制轉換為您正在訪問的對象類型。
並且因為它沒有指向任何一種類型的對象,所以沒有適當的方法對void *
指針執行指針運算。
無論指向的數據類型如何,指針的大小都是相同的。
這不一定是真的 - 指向不同類型的指針可能具有不同的大小和表示:
指向void
的指針應具有與指向字符類型的指針相同的表示和對齊要求。
48)類似地,指向兼容類型的合格或非限定版本的指針應具有相同的表示和對齊要求。
所有指向結構類型的指針都應具有相同的表示和對齊要求。
所有指向union類型的指針都應具有相同的表示和對齊要求。
指向其他類型的指針不需要具有相同的表示或對齊要求 。
C 2011在線草案 ,§6.2.5¶28
指針類型的值表示是實現定義的。 布局兼容類型的指針應具有相同的值表示和對齊要求(3.11)。
C ++ 2014工作草案 ,§3.9.2,¶3
在大多數現代桌面和服務器上它們是相同的,但不要指望它是普遍真實的。
那為什么我們需要聲明它指向的數據類型?
指針算法取決於指向類型 - 如果p
指向類型為T
的對象,則p + 1
指向類型為T
的下一個對象。 由於不同類型具有不同的大小,因此您需要知道指向類型以正確計算偏移量。
那么,為什么我們不能概括這樣的指針聲明
pointer p; //where p is an object of pointer class.
你實際上可以使用void*
。 但結果是在那一點上所有類型(和大小信息)都丟失了。
你必須以某種方式(硬編碼類型轉換或其他)跟蹤它,以使其有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.