简体   繁体   English

在指向结构的指针中访问数组

[英]Accessing arrays in a pointer to a struct

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. 例如,对于整数数组, value是sizeof(int)。

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): 如果在另一个函数中我想在d-> thing中插入一些东西(假设至少不是,我只是将其添加到第一个插槽中,则在其他位置进行位置管理):

char * thing = "Me!";
strncpy(d->things[0], &thing, d->sizeOfThings);

I get around the strncpy area 我绕过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

I'm just trying to understand the use of void* as a way to generalize my functions. 我只是想了解使用void *作为泛化函数的一种方式。 I suspect there's something wrong with d->things[0] . 我怀疑d->things[0]

According to the C standard, void has no size-- sizeof(void) is undefined. 根据C标准,void没有大小-sizeof(void)是未定义的。 (Some implementations make it sizeof(int) but this is non-compliant.) (某些实现使它的大小为sizeof(int),但这是不兼容的。)

When you have an array of type foo, this expression: 当您拥有foo类型的数组时,此表达式:

array[3]

Adds 3*sizeof(foo) to the address stored in array and then deferences that. 将3 * sizeof(foo)添加到数组中存储的地址中,然后对其进行引用。 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.) 由于sizeof(void)是未定义的,因此您不能对void数组执行此操作(实际上,您甚至不能拥有 void数组,而只能具有void指针。)

You must cast any void pointer to another pointer type before treating it as an array: 在将其视为数组之前,必须将任何void指针强制转换为另一种指针类型:

d->things = malloc(20 * sizeof(int));
(int *)(d->things)[0] = 12;

However, keep in mind that you don't even have to do that to use strncpy on it. 但是,请记住,甚至不需要在其上使用strncpy。 Strncpy can accept a void pointer just fine. Strncpy可以接受void指针。 But you were using strncpy incorrectly. 但是您使用的strncpy错误。 Your strncpy invocation should look like this: 您的strncpy调用应如下所示:

strncpy(d->things, thing, d->sizeOfThings);

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 *. 您的版本将要做的是尝试将d-> things的第一个数组成员视为指针,而不将其视为指针,并且将&thing视为char **,就好像它只是char *。

Demo *d = malloc(sizeof(Demo));
if (d != NULL) {
    d->things = malloc(20 * sizeOfThings); // We'll have a max of 20 things
}

What is sizeOfThings initialized to ? sizeOfThings初始化为什么? Probably it might have garbage and is causing the error. 可能是有垃圾,并导致了错误。 Even if it is initialized to 0 by default, then malloc returns NULL( malloc( 20 * 0 ) ; ). 即使默认将其初始化为0malloc也会返回NULL( malloc( 20 * 0 ) ; )。 And so, I suspect - 因此,我怀疑-

strncpy(d->things[0], &thing, d->sizeOfThings);
      // ^^^^^^^^^^ causing the error.

Try to see if this fixes your problem: 尝试查看是否可以解决您的问题:

char *thing = "Me!";
strncpy(&d->things[0], thing, d->sizeOfThings);

Then, cast the pointers to get rid of the warnings, but you have to make sure what you're going to do 然后,强制释放指针以摆脱警告,但是您必须确保要执行的操作

char *thing = "Me!";
strncpy((char *) &d->things[0], (const char *) thing, d->sizeOfThings);

Two things: 两件事情:

Firstly, there's definitely something wrong with using d->things[0] . 首先,使用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. d-> things实际上是一个指针,约定是指针和数组基本上可以互换(有一些例外),并且数组名称始终指向数组的第一个元素。

Secondly, the functional signature of strncpy is char* strncpy(char* destination, const char* source, size_t num); 其次,strncpy的功能签名是char * strncpy(char *目标,const char *源,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&). 因此,要使此工作有效,我们必须将d-> thing从void *转换为char *,并确保我们将事物作为char *(只是事物)与char **(这是事物&)传递。

so we want this statement instead: 因此,我们希望使用以下语句:

strncpy((char*)d->things, thing, d->sizeOfThings); strncpy((char *)d->事物,事物,d-> sizeOfThings);

Once the changes are in place, the rest of the code compiles and runs as expected. 更改到位后,其余代码将按预期编译并运行。

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

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