[英]Assigning (a pointer to an array of integers) to (a pointer to an integer array cast as a void pointer) in C
我遇到過類似以下的C代碼:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a = malloc(200*sizeof(int));
int i;
for (i = 0; i < 200; i++)
{
a[i] = i;
}
int (*b)[10] = (void*) a;
printf("\nsizeof(int):\t%d\n", sizeof(int));
printf("\nb[0]:\t%d\n", b[0]);
printf("\na:\t%d\n", a);
printf("\nb[19]:\t%d\n", b[19]);
printf("\na+190:\t%d\n", a+190);
printf("\nb[0][8]:\t%d\n", b[0][8]);
printf("\nb[19][9]:\t%d\n", b[19][9]);
return 0;
}
根據我的理解,行int (*b)[10] = (void*) a;
試圖將指針b
(應該指向10個整數的數組)分配給數組的起始地址作為無效指針a
類型轉換。 我本來期望b[i]
來保持相同的數據, a[i]
為i=0..9
(和0以外的任何索引至9 b
導致一些不確定的行為)。 但是,該程序產生的輸出類似於以下示例:
sizeof(int): 4
b[0]: 9768976
a: 9768976
b[19]: 9769736
a+190: 9769736
b[0][8]: 8
b[19][9]: 199
顯然, b
已成為一個包含20個指針的數組,每個元素指針指向a
數組的唯一部分,每個部分對應10個整數(或40個字節)。 有人可以解釋一下究竟是什么int (*b)[10] = (void*) a;
呢? 具體而言,如何做類型轉換(void *)
在分發整個幫助a
跨越的多個元素b
? 如果沒有(void *)
強制轉換,上面的代碼就無法編譯。
看看它是這樣的:
int *a;
a = malloc(200 * sizeof(int));
int (*b)[10];
b = (void *)a;
所以,第一行說的是a
應指向一個int
。 第二行分配一個可以容納200個int
的內存塊,並將該塊的起始地址分配給a
。 第三行說b
應該指向一個10 int
的數組。 第四行表示, b
應分配所持地址a
。
所以現在b
指向一個10個int
的數組,從調用malloc()
返回的地址開始。 由於內存分配為200個int
,因此b
指向一個可容納20個10元素int
的內存塊。
演員到void
是必要的,因為a
被宣布為一個指針int
; 這使您可以通過存儲保存的值a
在b
,即使他們是不同類型的。 我認為這只是為數組分配適當內存量的方便。 一種替代方法,避免的聲明a
完全,將是:
int (*b)[10] = malloc(20 * sizeof(*b));
根據讀者的口味,這第二種方法可能會或可能不會更加神秘。 我猜第一種方法的一個優點是它允許您按順序和作為二維數組訪問數組的元素。
顯然,
b
已成為一個包含20個指針的數組,每個元素指針指向a
數組的唯一部分,每個部分對應10個整數(或40個字節)。
不, b
只是一個指針,而不是一個數組。 類型b
指向的是10- int
的數組。 如果你認為這可能會更簡單:
typedef int row[10]; // A `row` is an array of 10 ints
row* b = (void*) a;
對於任何指針T* p
, p[n]
是從p[n - 1]
偏移的sizeof (T)
字節(假設n
和n - 1
是有效的索引,當然)。 這個案子沒有什么不同; 這里的T
是一個10元素的int
數組,因此b
每個元素都是10 * sizeof (int)
字節,遠離其相鄰元素。
具體而言,如何做類型轉換
(void *)
在分發整個幫助a
跨越的多個元素b
? 如果沒有(void *)
強制轉換,上面的代碼就無法編譯。
在C中,指針可以在void*
和T*
之間轉換而無需顯式轉換。 上面的案例使用void*
cast來減少打字; 它允許將右側轉換為左側所需的任何指針類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.