访问结构体指针中的数组
我有一个简单的结构:
typedef struct {
void *things;
int sizeOfThings;
} Demo;
things 旨在包含一系列单独的“thing”,例如字符串或整数。 我创建了一个指向它的指针:
Demo * Create(int value) {
Demo *d = malloc(sizeof(Demo));
if (d != NULL) {
d->sizeOfThings = value;
d->things = malloc(20 * value); // We'll have a max of 20 things
}
}
例如,对于整数数组,value
是 sizeof(int) 。
如果在另一个函数中我想将某些内容插入到 d->things 中(至少假设我只是将其添加到第一个插槽,位置管理在其他地方完成):
char * thing = "Me!";
strncpy(d->things[0], &thing, d->sizeOfThings);
我绕过了 strncpy 区域
test.c:10: warning: pointer of type ‘void *’ used in arithmetic
test.c:10: warning: dereferencing ‘void *’ pointer
test.c:10: error: invalid use of void expression
,我只是在尝试理解 void* 的使用作为概括我的函数的一种方式。我怀疑 d->things[0]
有问题。
I have a simple struct:
typedef struct {
void *things;
int sizeOfThings;
} Demo;
things is intended to contain an array of individual "thing", like maybe strings or ints.
I create a pointer to it:
Demo * Create(int value) {
Demo *d = malloc(sizeof(Demo));
if (d != NULL) {
d->sizeOfThings = value;
d->things = malloc(20 * value); // We'll have a max of 20 things
}
}
value
is sizeof(int) for an array of ints, for example.
If in another function I want to insert something into d->things (assuming at least for not that I'm just adding it to the first slot, position management done elsewhere):
char * thing = "Me!";
strncpy(d->things[0], &thing, d->sizeOfThings);
I get around the strncpy area
test.c:10: warning: pointer of type ‘void *’ used in arithmetic
test.c:10: warning: dereferencing ‘void *’ pointer
test.c:10: error: invalid use of void expression
I'm just trying to understand the use of void* as a way to generalize my functions. I suspect there's something wrong with d->things[0]
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据 C 标准,void 没有大小—— sizeof(void) 未定义。 (有些实现将其设置为 sizeof(int),但这不符合要求。)
当您有一个 foo 类型的数组时,此表达式:
将 3*sizeof(foo) 添加到数组中存储的地址,然后引用该地址。这是因为这些值都打包在内存中。由于 sizeof(void) 未定义,因此您不能对 void 数组执行此操作(事实上,您甚至不能有 void 数组,只能有 void 指针。)
您必须将任何 void 指针转换为另一个指针在将其视为数组之前键入:
但是,请记住,您甚至不必这样做即可对其使用 strncpy。 Strncpy 可以很好地接受 void 指针。但是您错误地使用了 strncpy 。您的 strncpy 调用应如下所示:
您的版本会尝试将 d->things 的第一个数组成员视为指针(当它不是时),并且会处理 &thing,它是一个 char **,就好像它只是一个 char * 一样。
According to the C standard, void has no size-- sizeof(void) is undefined. (Some implementations make it sizeof(int) but this is non-compliant.)
When you have an array of type foo, this expression:
Adds 3*sizeof(foo) to the address stored in array and then deferences that. That's because the values are all packed together in memory. Since sizeof(void) is undefined, you can't do that for void arrays (in fact you can't even have void arrays, only void pointers.)
You must cast any void pointer to another pointer type before treating it as an array:
However, keep in mind that you don't even have to do that to use strncpy on it. Strncpy can accept a void pointer just fine. But you were using strncpy incorrectly. Your strncpy invocation should look like this:
What your version would have done was try to treat the first array member of d->things as a pointer when it's not, and would have treated &thing, which is a char **, as if it were just a char *.
尝试看看这是否可以解决您的问题:
然后,投射指针以消除警告,但您必须确定要做什么
Try to see if this fixes your problem:
Then, cast the pointers to get rid of the warnings, but you have to make sure what you're going to do
sizeOfThings
初始化为什么?可能它可能有垃圾并导致错误。即使默认情况下将其初始化为 0,malloc
也会返回 NULL(malloc( 20 * 0 ) ;
)。所以,我怀疑——What is
sizeOfThings
initialized to ? Probably it might have garbage and is causing the error. Even if it is initialized to 0 by default, thenmalloc
returns NULL(malloc( 20 * 0 ) ;
). And so, I suspect -有两件事:
首先,使用 d->things[0] 肯定有问题。 d->things 实际上是一个指针,约定是指针和数组基本上可以互换(有一些例外),并且数组名称将始终指向数组的第一个元素。
其次,strncpy 的函数签名是char* strncpy(char* destination, const char* source, size_t num);。因此,为了使这项工作有效,我们必须将 d->thing 从 void* 转换为 char* 并确保我们将 thing 作为 char* (只是东西)与 char** (即 thing&)传递。
所以我们想要这样的声明:
更改到位后,其余代码将按预期编译并运行。
Two things:
Firstly, there's definitely something wrong with using d->things[0]. d->things is actually a pointer and the convention is that pointers and arrays are basically interchangeable (with a few exceptions) and the array name will always point to the first element of the array.
Secondly, the functional signature of strncpy is char* strncpy(char* destination, const char* source, size_t num);. So to make this work, we have to cast d->thing from void* to char* and make sure that we pass thing as a char* (just thing) vs. a char** (which is thing&).
so we want this statement instead:
Once the changes are in place, the rest of the code compiles and runs as expected.