简体   繁体   English

在C中将(指向整数数组的指针)分配给(指向作为void指针的整数数组的指针)

[英]Assigning (a pointer to an array of integers) to (a pointer to an integer array cast as a void pointer) in C

I have come across a C code similar to the following: 我遇到过类似以下的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;
}

As per my understanding, the line int (*b)[10] = (void*) a; 根据我的理解,行int (*b)[10] = (void*) a; is trying to assign pointer b (which is supposed to point to an array of 10 integers) to the starting address of array a typecast as a void pointer. 试图将指针b (应该指向10个整数的数组)分配给数组的起始地址作为无效指针a类型转换。 I would have expected b[i] to hold the same data as a[i] for i=0..9 (and any index other than 0 to 9 for b resulting in some undefined behavior). 我本来期望b[i]来保持相同的数据, a[i]i=0..9 (和0以外的任何索引至9 b导致一些不确定的行为)。 However, the program produces outputs similar to the following sample: 但是,该程序产生的输出类似于以下示例:

sizeof(int):    4

b[0]:   9768976

a:      9768976

b[19]:  9769736

a+190:  9769736

b[0][8]:        8

b[19][9]:       199

Clearly, b has become an array of 20 pointers, with each elemental pointer pointing to a unique portion of the a array corresponding to 10 integers (or 40 bytes) each. 显然, b已成为一个包含20个指针的数组,每个元素指针指向a数组的唯一部分,每个部分对应10个整数(或40个字节)。 Can someone please explain what exactly int (*b)[10] = (void*) a; 有人可以解释一下究竟是什么int (*b)[10] = (void*) a; does? 呢? Specifically, how does the typecast (void *) help in distributing the entire a across multiple elements of b ? 具体而言,如何做类型转换(void *)在分发整个帮助a跨越的多个元素b The above code would not compile without the (void *) cast. 如果没有(void *)强制转换,上面的代码就无法编译。

Look at it like this: 看看它是这样的:

int *a;
a = malloc(200 * sizeof(int));

int (*b)[10];
b = (void *)a;

So, the first line says that a should point to an int . 所以,第一行说的是a应指向一个int The second line allocates a block of memory that can hold 200 int s, and assigns the address of the start of this block to a . 第二行分配一个可以容纳200个int的内存块,并将该块的起始地址分配给a The third line says that b should point to an array of 10 int s. 第三行说b应该指向一个10 int的数组。 The fourth line says that b should be assigned the address held by a . 第四行表示, b应分配所持地址a

So now b points to an array of 10 int s starting at the address returned from the call to malloc() . 所以现在b指向一个10个int的数组,从调用malloc()返回的地址开始。 Since memory was allocated for 200 int s, b points to a block of memory that can hold 20 10-element arrays of int . 由于内存分配为200个int ,因此b指向一个可容纳20个10元素int的内存块。

The cast to void is needed because a was declared to be a pointer to int ; 演员到void是必要的,因为a被宣布为一个指针int ; this allows you to store the value held by a in b , even though they are of different types. 这使您可以通过存储保存的值ab ,即使他们是不同类型的。 I think that this was a mere convenience in the allocation of the appropriate amount of memory for the array. 我认为这只是为数组分配适当内存量的方便。 An alternative method, avoiding the declaration of a altogether, would be: 一种替代方法,避免的声明a完全,将是:

int (*b)[10] = malloc(20 * sizeof(*b));

This second method might or might not seem a bit more cryptic, depending upon the readers tastes. 根据读者的口味,这第二种方法可能会或可能不会更加神秘。 I guess one advantage of the first method is that it allows you to access the elements of the array both sequentially and as a 2d array. 我猜第一种方法的一个优点是它允许您按顺序和作为二维数组访问数组的元素。

Clearly, b has become an array of 20 pointers, with each elemental pointer pointing to a unique portion of the a array corresponding to 10 integers (or 40 bytes) each. 显然, b已成为一个包含20个指针的数组,每个元素指针指向a数组的唯一部分,每个部分对应10个整数(或40个字节)。

No, b is just a pointer, not an array. 不, b只是一个指针,而不是一个数组。 The type b points to is array-of-10- int s. 类型b指向的是10- int的数组。 Perhaps this would be simpler if you consider it as: 如果你认为这可能会更简单:

typedef int row[10]; // A `row` is an array of 10 ints
row* b = (void*) a;

For any pointer T* p , p[n] is sizeof (T) bytes offset from p[n - 1] (assuming that n and n - 1 are valid indices, of course). 对于任何指针T* pp[n]是从p[n - 1]偏移的sizeof (T)字节(假设nn - 1是有效的索引,当然)。 This case is no different; 这个案子没有什么不同; here T is a 10-element int array, so each element of b is 10 * sizeof (int) bytes away from its adjacent elements. 这里的T是一个10元素的int数组,因此b每个元素都是10 * sizeof (int)字节,远离其相邻元素。

Specifically, how does the typecast (void *) help in distributing the entire a across multiple elements of b ? 具体而言,如何做类型转换(void *)在分发整个帮助a跨越的多个元素b The above code would not compile without the (void *) cast. 如果没有(void *)强制转换,上面的代码就无法编译。

In C, pointers can be converted between void* and T* without explicit casting. 在C中,指针可以在void*T*之间转换而无需显式转换。 The above case uses a void* cast for convenience by reducing typing; 上面的案例使用void* cast来减少打字; it allows the right-hand-side to be converted to whatever pointer type is needed by the left-hand-side. 它允许将右侧转换为左侧所需的任何指针类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM