[英]dereference local array in C
根據我對C的理解,您可以將指針變量和數組變量視為等效變量,因為它們最終都是指針(一個指向本地函數堆棧,另一個指向內存中的任意隨機點)。
我通常在需要返回指針時將指針傳遞給指針(例如char ** pvar
),因此我可以看到將其傳遞回解引用的本地數組的意義不大,因為您無法更改位置變量
我的期望是,如果嘗試此操作,編譯器將允許我執行此操作,然后在嘗試設置返回指針值時出現段錯誤或崩潰。
但是,當嘗試取消對數組類型(&array)的引用時,編譯器會有用地生成有關使用不兼容類型的警告,然后將指針傳遞給數組,從接收函數的角度來看,本質上會失去一種間接級別。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void ptrptr(uint32_t** dptr)
{
printf("%x, %x\n", dptr, *dptr);
}
void oneptr(uint32_t* ptr)
{
printf("%08x, %x\t", ptr, *ptr);
ptrptr(&ptr);
}
int main()
{
uint32_t array[] = {1};
uint32_t *ptr = calloc(1, sizeof( uint32_t));
ptr[0] = 3;
oneptr(ptr); /* OK, passes an (uint32_t *) */
oneptr(array); /* OK, passes an (uint32_t *) */
ptrptr(&ptr); /* OK, passes an (uint32_t **) */
ptrptr(&array); /* ??, passes an (uint32_t *) */
return 0;
}
編譯它給我警告
cc test.c -o test
test.c: In function ‘main’:
test.c:24:9: warning: passing argument 1 of ‘ptrptr’ from incompatible pointer type [-Wincompatible-pointer-types]
ptrptr(&array);
^
test.c:5:6: note: expected ‘uint32_t ** {aka unsigned int **}’ but argument is of type ‘uint32_t (*)[1] {aka unsigned int (*)[1]}’
void ptrptr(uint32_t** dptr)
^~~~~~
0061a008, 3 7ebfa144, 61a008
7ebfa154, 1 7ebfa144, 7ebfa154
7ebfa150, 61a008
7ebfa154, 1
當我使用gcc,clang和cl進行編譯時,我會得到相同的結果,因此我非常有信心這不是編譯器錯誤。 然后的問題是,為什么在我嘗試取消引用數組時,C為何靜默傳遞指針( uint32_t*
)而不是指針( uint32_t**
)的指針?
然后的問題是,為什么在我嘗試取消引用數組時,C為何靜默傳遞指針(
uint32_t*
)而不是指針(uint32_t**
)的指針?
不是。
C正在傳遞一個指向一個uint32_t( uint32_t(*)[1]
)數組的指針。
它是一個uint32_t數組的指針,因為它是一個uint32_t數組,並且您有一個指向它的指針。
這不是沉默。 您會收到一個編譯器警告,提示“嘿,這是錯誤的指針類型!”。 您認為這是什么?
test.c: In function 'main': test.c:24:9: warning: passing argument 1 of 'ptrptr' from incompatible pointer type [-Wincompatible-pointer-types] ptrptr(&array); ^ test.c:5:6: note: expected 'uint32_t ** {aka unsigned int **}' but argument is of type 'uint32_t (*)[1] {aka unsigned int (*)[1]}' void ptrptr(uint32_t** dptr)
您沒有取消引用數組。 您正在創建一個指向數組的指針,將其轉換為錯誤的指針類型,然后取消引用。
之所以給您數字1的原因是因為指向數組的指針實際上指向的地址與指向數組中第一件事的指針相同。 雖然,這是一種不同類型的指針,這意味着++
類的東西工作方式不同,但是隨后您將其轉換為相同類型的指針,因此您的代碼不會注意到。
然后的問題是,為什么在我嘗試取消引用數組時,C會靜默傳遞指針(uint32_t *)而不是指針(uint32_t **)的指針?
這不是沉默,它給了您警告。 C標准沒有提到術語“錯誤”和“警告”,而是提到了診斷消息。 要遵循C標准,只要編譯器向程序員顯示診斷消息就足夠了。
如果您想使用gcc或clang而不是針對C標准違反的警告而不是警告,則必須使用-std=c11 -pedantic-errors
編譯。
至於為什么代碼不正確, &array
以數組指針uint32_t(*)[1]
的形式給出&array
的地址。 此類型與uint32_t**
不兼容。 未指定運行包含C標准約束違例的程序將不會發生的事情:它是未定義的行為。 不能保證段錯誤或崩潰,這只是未定義行為的許多潛在結果中的兩個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.