簡體   English   中英

使用 (unsigned int *) 和 (unsigned int **) 進行的 void 指針類型轉換

[英]void pointer type cast with (unsigned int *) and (unsigned int **)

unsigned int num = 101;

void * p = #

void ** pp = &p;

unsigned int *get_data_1 = NULL;
unsigned int *get_data_2 = NULL;

get_data_1 = *((unsigned int *)pp);

get_data_2 = *((unsigned int **)pp);

這里get_data_1get_data_2會有什么區別呢?

我使用 (unsigned int *) 和 (unsigned int **) 進行類型轉換。

這兩個操作都會調用Undefined Behavior pp指向的類型void*的值分別通過不兼容類型unsigned intunsigned int*的左值表達式訪問。 這違反了嚴格的別名規則。

由於這兩個操作都是UB ,因此這兩個操作之間沒有明確的區別

正確的訪問應該是首先取消引用pp以獲得void*類型的值並使用從void*unsigned int*的隱式轉換。 最后取消引用正確類型的指針:

unsigned int *get_data_3 = *pp;
return *get_data_3;

TL;博士

不要這樣做,出於多種原因,這是危險且不正確的 C 語言。 我對初學者的一般建議是永遠不要使用 cast 運算符 - 不應該有很多情況下您實際上需要使用它。


通常,只要不存在與指向的類型有關的對齊問題,C 允許在不兼容的對象指針之間進行狂野和危險的指針轉換。 (6.3.2.3/7)

但是,如果您首先轉換為不兼容的類型,然后取消引用指針,則可能會出現各種未定義的行為。6.7.6.1:

對於要兼容的兩種指針類型,兩者都應具有相同的限定,並且都應是指向兼容類型的指針。

還有關於“左值訪問”(6.5)的整個“嚴格別名”問題。

具體來說:

  • (unsigned int *)pp指針轉換可能沒問題,因為pp指向對齊的地址。
  • *((unsigned int *)pp)調用未定義的行為,因為void*類型的左值作為unsigned int訪問,並且它們不是兼容的類型。
  • unsigned int *get_data_1 = <unsigned int lvalue>是違反約束的 - 無效 C。根據 6.5.16.1。 C 從未允許將整數分配給指針,反之亦然,需要顯式轉換。
  • (unsigned int **)pp同樣,指針轉換本身“可能還可以”。 但同樣unsigned int**void**不兼容。 值得注意的是,關於void*轉換的特殊通用規則不適用於void**
  • *((unsigned int **)pp)void*作為unsigned int*訪問。 這又是一個嚴格的別名違規,因為盡管我們可以將 void* 轉換為/從void*轉換為任何對象指針,但它們不需要具有相同的內部表示(盡管在實踐中很有可能)。 根據引用的 6.7.6.1,它們不是兼容的類型。
  • unsigned int *get_data_2 = <unsigned int* lvalue>沒問題。

暫無
暫無

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

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