[英]Confused about the pointers and generic(void) pointers in C
我錯過了幾個課程,並沒有真正理解流動的演講幻燈片關於void指針的例子。
在“no,no,no”這一行中,為什么我們不能因為P被分配了一個真正的指針類型q而不需要P?
在“??”行中,將指針強制轉換為整數是否合法? (我認為它可以編譯,因為C不會檢查強制轉換,但不知道它將獲得什么樣的結果
在此示例中將整數指針轉換為整數
他投了* p = 10; a =(int)p; 並且有人回答說a將是一個非常大的價值。 但在我的情況下,是(int)* p ...是否與我上面給出的例子相同?
“void *”的意思是“這個值是指向某個東西的指針,但我並沒有告訴你它指向的是什么”。 從這個陳述開始,一切都有意義。
所以應該清楚的是,你不能取消引用空白*,因為沒有人告訴你它指向的是什么 ! 如果您不知道它是指向int,char還是某個struct,那么如果您取消引用它,您認為會發生什么?
在C中,您可以為任何指針指定void *,例如指定給int *。 編譯器不知道 void *指向的是什么,但是當你寫r = p時; 編譯器說“我希望你知道你在做什么,我相信你。”(同樣情況下的C ++編譯器不信任你)。 如果void * p確實指向了int,那么一切都很好。 否則,事情或多或少都會變壞。
?? ?? 一個是錯的。 你不能解除引用* p。 不管你事后做什么,* p是不允許的。 並且沒有指針被轉換為整數。 嘗試取消引用指針,這是不允許的。 取消引用的結果可能沒有任何用處,因為你不知道p指向什么,所以你沒有什么用於強制轉換為int。
現在在*(int *)中發生的事情:p:p是一個void * - 指向某個東西的指針,但你不知道它指向的是什么。 (int *)p是強制轉換:p轉換為int *。 這意味着編譯器會相信(int *)p指向一個int - 可能是也可能不是。 *(int *)p取消引用int *:總的來說,你說服編譯器p指向一個int,並讀取p希望指向的int。 如果p確實指向了int,那很好。 如果p沒有指向int,那你就麻煩了。
無效指針是特定的指針,它們沒有與之關聯的數據類型。 您必須將它們重新轉換為特定類型(即:int *)才能訪問其內容。
澄清您的具體要點:
1)雖然p可能有一個指針地址,但它沒有與之關聯的特定數據類型(數據類型是訪問內容所必需的)
2)這個動作的結果可能是內容的確定性。 我不建議這是一個好習慣。
3)這告訴編譯器將void指針視為整數指針。 因此,它“知道”與之關聯的數據類型,並將其作為int訪問。
在“no,no,no”這一行中,為什么我們不能因為P被分配了一個真正的指針類型q而不需要P?
int a =2, *q = a, *r; //line 1
void *p; //line 2
p = q; // line 3
r = p; // line 4
使用上面的第3行,您將指針q
指定給p
。 但它並沒有改變p
的類型 - 它仍然是一個無效指針。 所以你不能取消引用它。 所以以下內容無效:
printf("%d\n", *p); // p is a void pointer - dereferencing here is illegal
或者,你可以這樣做:
printf("%d\n", *((int*) p)); // p is a void pointer
以上是有效的。 因為,我們在解除引用之前將p
轉換為int *
。 考慮一個例子,
void func(void *p)
{
// what's `p` point to here?
}
int main(void)
{
int i = 5;
long x = 10;
void *p;
p = &i; // line 1
p = &x; //line 2
func(p);
}
您可以注釋掉line1或line2,但是在func()
中是否存在以確定p
是指向long
數據還是int
數據? 這與你的情況沒什么不同。
但是在訪問它指向的數據之前,始終需要從void *
到type *
(數據指針)的轉換。 請注意,它不能是任何數據指針。 例如,
int i = 42;
float f = 4.0;
void *p = &f;
printf("%d\n", *((int*))p); // wrong!
這是非法的。 p
指向float *
。 取消引用好像它指向一個int
數據是錯誤的。
在“??”行中,將指針強制轉換為整數是否合法?
printf("%d\n", (int) *p);
由於p
是void*
,因此首先不允許取消引用。 解除引用后的強制轉換不會改變任何內容,並且取消引用是非法的。
如果您要將指針本身轉換為:
printf("%d\n", (int)p);
這在C中具有實現定義的行為.C還為整數到指針轉換提供intptr_t
/ uintptr_t
類型。
如果指針p
類型為void *
,則表達式*p
類型為void
,而void
類型的值不為1 ; 這就是為什么你必須在解除引用它之前將指針轉換為“真正的”指針類型。
指針和整數可以相互轉換,但不保證這些值有意義。 但是,這不是標記的線??
是在做; 它試圖取消引用p
並轉換結果,但由於p
是指向void
的指針,因此不允許這樣做。
表達式*((int *) p)
將p
從指向void
的指針轉換為指向int
指針,並取消引用結果。 由於p
指向a
,因此計算為a
( 2
)的值。
void
類型是不完整的類型,無法完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.