空指针数组的指针

8

我有一个void指针数组,想要访问其中的元素(初始化它们),但是无法实现:

void* anyptr = ...; //a pointer to something
void* arr = (void*)malloc(sizeof(void*)*10);

int i=0;
for(i=0; i<10; i++)
   *(arr+i) = anyptr; //dont work, (arr+n) = anyptr; doesn´t work too

我猜这不起作用的原因是左侧是元素i的结果。但是我不知道如何解决这个问题。

5
为什么你要将 void * 强制转换成 void *?无论如何,你都不应该进行这样的强制转换。(参见:https://dev59.com/dHRB5IYBdhLWcg3wgHWr) - user529758
*(arr+i) 空指针解引用。 - BLUEPIXY
8
对于一个不知道自己在做什么的人提问“你为什么这么做?”几乎总是听起来很粗鲁而且不具有教育意义。 - Rafael Eyng
3个回答

28

在C语言中,有两种初始化数组的方式:

  • 上(由于函数结束时会被自动清理内存,因此不需要手动处理)
  • 上(需要手动分配和释放内存)

如果您想使用栈,您可以像这样初始化数组...

#define ARRAY_LENGTH 10
void *ptr;
void *arr[ARRAY_LENGTH];
for (int i = 0; i < ARRAY_LENGTH; i++) {
    arr[i] = ptr;
}

你可以按照类似的方式在堆中定义数组,方法如下...

#define ARRAY_LENGTH 10
void *ptr;
void **arr = malloc(sizeof(void *) * ARRAY_LENGTH);
for (int i = 0; i < ARRAY_LENGTH; i++) {
    arr[i] = ptr;
}
free(arr);

记住,数组(除了在堆栈中分配的数组,它们有一些额外的属性,例如长度)本质上只是指向第一个元素的指针,而操作arr[i]相当于从第一个元素移动i*sizeof(elem)个字节,并访问那里的内存。如果你想获得指向数组中第i个索引的指针,则可以使用以下表示法...

void *indexPtr = arr + i;
或者
void *indexPtr = &( arr[i] );

按照这种方式,一个 void* 数组的类型应该是 void **,因为变量是指向数组第一个成员的指针,而这个成员本身也是一个指针。这可能有点令人困惑,但要始终记住数组元素的类型,并创建指向它们的指针。所以,如果数组是 int 类型的,那么数组将是 int int[] 类型的,但如果您要存储指向整数的指针,您需要用这两种形式之一初始化一个 int * 类型的数组...

int **arr = malloc(sizeof(int *) * ARRAY_LENGTH);
int *arr[ARRAY_LENGTH];

请注意,您正在存储指针,因此如果运行代码...

int *arr[4];
for (int i = 0; i < ARRAY_LENGTH; i++) {
    arr[i] = &i;
}
尽管数组中指向的值看起来应该是[0, 1, 2, 3],但实际上它将是[4, 4, 4, 4],因为你所拥有的是一个指向函数中变量i的所有指针数组,所以每当你更改i时,数组中指向的值都会被更改。
希望这可以帮到你。

我从malloc指令中得到了error: invalid conversion from ‘void*’ to ‘void**’ [-fpermissive]错误,有什么想法吗? - Aurelien Montmejat
1
使用 void **arr = (void **)malloc(sizeof(void *) * 10) 解决了我的问题! - Aurelien Montmejat

12

你需要修改这一行

void* arr = (void*)malloc(sizeof(void*)*10);

到这里

void** arr = malloc(sizeof(void*)*10);

请问能否解释一下为什么它被声明为指向指针的指针? - init
3
@init 是因为你正在分配内存给10个指针。如何指向这段内存呢?你需要指向第一个指针,因此它是指向指针的指针。你将其加1,就可以指向下一个指针,直到最后一个指针。 - Alexey Frunze

3
你不能对一个空指针进行间接寻址操作。这是空指针的全部意义所在。
通过间接寻址指针,你可以访问指针所指向地址上的数据项。然而,使用空指针时,你不知道目标对象的大小(它是一个1B的字符还是一个100B的结构体?),因此在进行间接寻址之前必须将其转换为特定的指针类型。
将整数i添加(或减去)到指针中,就相当于在指针的内容中添加i乘以sizeof(*pointer)次大小。 (只有当你的指针具有特定类型时,才能确定sizeof(* pointer)。使用空指针进行指针算术运算是没有意义的)。
至于(arr + n)= anyptr;,arr + n只是一个地址。 它不是可以分配任何值的值(不是左值)。

我该如何更改地址 arr+n 上的值? - 0xDEADBEEF
通过将其转换为特定的指针类型,然后取消引用它来实现。但请注意,如果ptr是非void指针,则ptr + n将意味着在ptr之前n个项目,这不一定意味着n个字节(对于char *指针来说是这样,但对于int指针来说,它很可能意味着n * 4个字节,对于任何类型的指针到指针(它将意味着4 * n或8 * n取决于您的架构(32位或64位)。 - Petr Skocik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接