我有一个简单的结构:
typedef struct {
void *things;
int sizeOfThings;
} Demo;
things旨在包含一个单独的"thing"数组,比如字符串或int。我创建了一个指向它的指针:
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
}
}
例如,对于int数组,value
是sizeof(int(。
如果在另一个函数中,我想把一些东西插入d->东西中(至少假设我只是把它添加到第一个槽中,位置管理在其他地方完成(:
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]
有问题。
根据C标准,void没有大小--sizeof(void(未定义。(有些实现将其设置为sizeof(int(,但这是不兼容的。(
当你有一个foo类型的数组时,这个表达式:
array[3]
将3*sizeof(foo(添加到存储在数组中的地址,然后对其进行延迟。这是因为这些值都被打包在内存中。由于sizeof(void(是未定义的,您不能对void数组执行此操作(事实上,您甚至不能拥有void数组,只有void指针。(
在将任何void指针处理为数组之前,必须将其强制转换为另一种指针类型:
d->things = malloc(20 * sizeof(int));
(int *)(d->things)[0] = 12;
但是,请记住,在上面使用strncpy甚至不必这样做。strncpy可以接受void指针。但您使用strncpy的方式不正确。您的strncpy调用应该如下所示:
strncpy(d->things, thing, d->sizeOfThings);
您的版本会做的是尝试将d->事物的第一个数组成员视为指针,而不是指针,并且会将&东西,它是一个char**,就好像它只是一个char*。
试着看看这是否能解决你的问题:
char *thing = "Me!";
strncpy(&d->things[0], thing, d->sizeOfThings);
然后,抛出指针以消除警告,但你必须确保你要做什么
char *thing = "Me!";
strncpy((char *) &d->things[0], (const char *) thing, d->sizeOfThings);
Demo *d = malloc(sizeof(Demo));
if (d != NULL) {
d->things = malloc(20 * sizeOfThings); // We'll have a max of 20 things
}
sizeOfThings
初始化为什么?它可能有垃圾,并导致错误。即使默认情况下初始化为0,malloc
也会返回NULL(malloc( 20 * 0 ) ;
(。所以,我怀疑-
strncpy(d->things[0], &thing, d->sizeOfThings);
// ^^^^^^^^^^ causing the error.
两件事:
首先,使用d->things[0]肯定有问题。d->things实际上是一个指针,惯例是指针和数组基本上是可互换的(只有少数例外(,数组名称总是指向数组的第一个元素。
其次,strncpy的函数签名是char*strncpy(char*destination,const-char*source,size_tnum(。因此,为了实现这一点,我们必须将d->thing从void*转换为char*,并确保我们将thing作为char*(just thing(与char**(即thing&(进行传递。
所以我们想要这个声明:
strncpy((char*(d->things,thing,d->sizeOfThings(
一旦更改到位,其余代码将按预期编译和运行。