我需要一些指针语法的帮助。我有一个结构数组,我试图从另一个结构中创建一个指向它的指针,包含在数组中。
struct foo array* = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
我已经阅读了这个问题:c pointer to array of structs。虽然它确实清除了一些混乱,但我仍然有一些错误需要解决。
我已经定义了这样的结构:
struct bar{
...
struct foo (*foo_ptr)[];
...
}
似乎我能够向数组中添加新结构,因为以下内容不会返回任何错误:
(*bar_arr[i]->foo_ptr)[j] = new_struct;
但是,如果我尝试在结构数组内部创建一个新的指针,如下所示:
struct foo* one_ptr = (*bar_arr[i]->foo_ptr)[j];
或者这个:
struct foo* one_ptr = bar_arr[i]->foo_ptr[j];
编译器会给我错误。任何一个用于无效使用带有未指定边界的数组,或者one_ptr和foo_ptr [j]具有不兼容的类型(在这种情况下:一个是foo类型,另一个是struct foo *)。
是否根本无法创建指向结构数组中某个元素的指针?任何帮助将不胜感激。
编辑:更好的代码示例
我目前正在使用线性链接列表作为共享内存堆栈,用于pthreads。结构数组是节点的共享池。无论何时从堆栈中删除节点,都会将其放入共享池中。如果一个线程试图将新项添加到堆栈中,它会检查池中是否存在要添加的元素,以避免每次需要向堆栈添加另一个元素时分配新内存。
每个线程都需要一个指向共享节点池的指针作为参数。这就是为什么我试图从参数结构创建一个指向它的指针。我希望这个问题有一个简单的答案。
typedef struct node{...} node_t;
struct thread_args
{
...
node_t (*pool)[];
...
}
node_t shared_pool = malloc(sizeof(node_t)*10);
arg[index]->pool = &shared_pool;
我正在尝试访问线程正在执行的其中一个函数中的池。
node_t *item;
item = stack->root;
//remove item from stack
(*args->pool)[index] = item;
//...later
node_t *item2;
item2 = (*args->pool)[index];
希望这能提供更多信息。
此外,我尝试使用的确切错误:
node_t *pool;
args[index]->pool = shared_pool;
如下:错误:从类型'node_t'分配类型'struct node_t *'时出现不兼容的类型。
答案 0 :(得分:2)
对于初学者来说这个声明(没有提到结束括号后省略的分号)
struct bar{
...
struct foo (*foo_ptr)[];
^^^
...
}
无效。您必须指定数组的大小。否则,指针将指向不称职类型的对象。
考虑到你如何尝试使用数组,这个声明没有意义。您可以将数据成员声明为
struct bar{
...
struct foo *foo_ptr;
...
};
然后
struct foo *array = malloc(sizeof(struct foo)*10);
bar_arr[i]->foo_ptr = array;
在这种情况下你可以写
bar_arr[i]->foo_ptr[j] = new_struct;
和
struct foo* one_ptr = bar_arr[i]->foo_ptr + j;
或
struct foo* one_ptr = &bar_arr[i]->foo_ptr[j];
答案 1 :(得分:1)
这是错误的:
struct foo array* = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
假设你的意思
struct foo *array = malloc(sizeof(foo)*10);
bar_arr[i]->foo_ptr = &array;
您将实际array
变量的地址存储到结构的foo_ptr
变量中。从您发布的代码片段中,可能是该函数的局部变量,因此它不仅是错误的类型,一旦函数返回它就不再存在。
给定struct foo
,这将分配一个指向struct foo
:
struct foo *array = malloc( nelem * sizeof( *array ) );
这将分配
bar_arr[i]->foo_ptr = array;
或者,更直接地说:
bar_arr[i]->foo_ptr = malloc( nelem * sizeof( *( bar_arr[i]->foo_ptr ) ) );
请注意,我使用指向malloc()
结果的指针取消引用作为sizeof()
的参数。这是确保指针和内存分配始终引用相同类型的简单方法。
对malloc()
的调用将分配nelem
struct foo
的连续副本(其中包含未知的,未指定的数据......)。这些副本可以通过
array[ n ]
只要n >= 0
和n < nelem
。
是否根本无法创建指向结构数组中某个元素的指针?
你的代码太复杂了。要创建指向n
元素的指针:
struct foo *nthElement = array + n;
您只需将n
添加到第一个元素的地址,结果指针将引用n
元素,假设n
在适当的范围内。
答案 2 :(得分:1)
foo_ptr
中struct bar
的声明不正确。将其更改为struct foo *foo_ptr
。并将您的赋值语句更改为以下
struct foo *array = malloc(sizeof(struct foo)*10);
bar_arr[i]->foo_ptr = array;
然后您可以读取或写入数组元素,如下所示
// read from array
struct foo one_struct = bar_arr[i]->foo_ptr[j];
// write to array
struct foo new_struct = { ... }
bar_arr[i]->foo_ptr[j] = new_struct;
(注意:读取和写入操作都是struct foo
的所有字段的副本。)
想想一个简单的例子。你如何制作10 char
的数组。
char *a = malloc(sizeof(char)*10)
a
是char
的指针,它指向包含10 char
的空格。所以我们可以将它用作数组。 a[4]
表示10 char
数组的第5 char
。
如果要将此数组分配给另一个变量,该怎么办?
char *b = a;
现在b
也是一个数组(不是原始数组的副本,b
和a
指向一个数组)。您现在可以通过b
引用该元素,就像您对a
所做的那样。例如,b[4]
。
没有人会将b
声明为char (*b)[]
对吗?
还是从一个简单的例子开始。当我们看到这样的声明 - char (*x)[10]
时 - 我们会对x
说些什么?我们可能会说x
是指向 10 char
数组的指针。
让我们看一下你的宣言struct foo (*foo_ptr)[]
。同样,我们可以说,foo_ptr
是指向... 长度未指定 struct foo
数组的指针。 (注意数组长度的不同。实际上不指定长度是错误的,我很快就会谈到它)
根据您的声明,让我们谈谈您在使用时遇到的错误。
struct foo* one_ptr = (*bar_arr[i]->foo_ptr)[j];
为简化并明确说明,我将在以下讨论中删除bar_arr[i]->
部分内容。
在此声明中,*foo_ptr
是一个长度未指定struct foo
的数组,我们可以这样称呼它,*foo_ptr
是struct foo []
的数组。因此(*foo_ptr)[j]
表示j
数组的struct foo []
元素。这里的一切似乎都很好。 但是你的数组没有定义长度,即使你为它分配了一个malloc数组,但是在编译时,gcc
并不知道它。这就是为什么它会引发关于&#34;未指定边界的错误&#34;。
struct foo* one_ptr = bar_arr[i]->foo_ptr[j];
如上所述,foo_ptr
是指向struct foo []
数组的指针。让我们注意foo_ptr
首先是指针的事实。因此,在此声明中,foo_ptr[j]
有点像*foo_ptr
。除了索引j
之外,它们具有相同的类型。由于我们已经知道*foo_ptr
是struct foo []
的数组,foo_ptr[j]
也是struct foo []
的数组。它是数组,而不是struct foo
的对象。准确地说,你需要想象有一个大数组,其中每个元素仍然是数组(struct foo []
数组)。在这个大数组中,foo_ptr[j]
只是j
元素,或者说j
数组。
因此,您将foo_ptr[j]
分配给one_ptr
的做法或多或少类似于以下示例
typedef char char_array_of_4_t[4];
char_array_of_4_t array1;
char *p = array1; //ERROR: incompatible types
为了便于理解,我在下面向您展示另一个例子。
char array2[4];
char *p = array2;
在第二个例子中,没有错误。从人类的角度来看,array1
和array2
都是4 char
的数组,但是,gcc
,array1
是一种数组,而array2
是一种指针。
答案 3 :(得分:0)
在此声明中......
struct bar{
// ...
struct foo (*foo_ptr)[];
// ...
};
... foo_ptr
的成员struct bar
被声明为指向未知长度数组struct foo
的指针。这是允许的,但这是不寻常的。通常只会声明一个指向数组第一个元素的指针,因为它在C中更自然地表现出来,而且它也更简单:
struct bar{
// ...
struct foo *foo_ptr;
// ...
};
您可以通过以下表单分配指向数组的成员:
bar_arr[i]->foo_ptr[j] = new_struct;
(当然,前提是指向数组至少有j + 1
个元素。要获得指向这样一个元素的指针,你可以做任何一个
struct foo *struct_ptr = &bar_arr[i]->foo_ptr[j];
或等同地
struct foo *struct_ptr = bar_arr[i]->foo_ptr + j;
您可以对原始结构声明执行相同操作,但表单需要略有不同。例如:
struct foo *struct_ptr = &(*bar_arr[i]->foo_ptr)[j];
但实际上,让每个人都更容易,包括你自己,并且不要那样做。