[英]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.