簡體   English   中英

對C中的指針和泛型(void)指針感到困惑

[英]Confused about the pointers and generic(void) pointers in C

我錯過了幾個課程,並沒有真正理解流動的演講幻燈片關於void指針的例子。

  1. 在“no,no,no”這一行中,為什么我們不能因為P被分配了一個真正的指針類型q而不需要P?

  2. 在“??”行中,將指針強制轉換為整數是否合法? (我認為它可以編譯,因為C不會檢查強制轉換,但不知道它將獲得什么樣的結果

在此示例中將整數指針轉換為整數
他投了* p = 10; a =(int)p; 並且有人回答說a將是一個非常大的價值。 但在我的情況下,是(int)* p ...是否與我上面給出的例子相同?

  1. 在最后一行,我對表達式感到困惑。 *((int *)p)實際上是= 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);

由於pvoid* ,因此首先不允許取消引用。 解除引用后的強制轉換不會改變任何內容,並且取消引用是非法的。

如果您要將指針本身轉換為:

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 ,因此計算為a2 )的值。


1. void類型是不完整的類型,無法完成。

暫無
暫無

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

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