如何解决如何通过另一个函数中的一个函数调整创建的数组的大小?
我在一个函数(比如 func1)中创建了一个数组,其中 _foo = set(foo)
_bar = set(bar)
in_foo = _foo - _bar
in_bar = _bar - _foo
的大小为 0。现在我需要另一个函数(比如 func2)来调整(即 calloc
)该数组的大小并填充它元素在那里。
然后在 func1 中,我将访问调整大小的数组的元素。
我不知道我怎么能这样做。
编辑:一些受访者要求我展示我的错误代码。这是代码
realloc
解决方法
realloc
使您的内存分配器有机会扩展或减少允许指针访问的空间量,而无需复制任何内容,然后在确实需要分配更多空间时处理复制。
然后它将返回您给它的指针(如果更改是就地的),或者返回数据所在新位置的指针(旧指针已释放,因此不要再次使用它)。如果您得到 NULL,则意味着您给它大小 0 并且它只是释放了您的数据,或者对于实际大小更改,分配失败并且您的原始指针仍然有效但大小未更改。
您遇到的问题是 func1 仍将具有原始指针。
最简单的解决方案是让 func2 返回新指针,或者在它们共享的全局值中更新它,如果这对您的程序没问题,或者 func1 可以将指针传递给 func2 指针,而 func2 可以使用和更新数据那个间接。
如果你想要一种更结构化的方法来共享它,你可以把指向指针的指针放在一个结构体中,并在它周围有一些辅助函数(有点像 golang 如何传递 { void * pointer,int size,int cap 的结构体} ( cap 未使用但分配了数组的一部分,因此 golang 可以在不立即调用 realloc 的情况下重新分配)
然后你可以做锁或其他任何事情,如果你将围绕数组进行线程化并将它们保持在该结构中,让助手帮助保持冷静。
如果您不必担心任何这些,只需将函数的指针作为返回值或作为 **out 参数返回即可。
什么是指针和数组?
C 不同于大多数高级语言。在大多数语言中,数组是您操作的数据结构。它会增长和缩小,并且可能有一堆与之相关的元数据和用于操作它的功能。这不是 C。
假设您有一个 int
。假设某处需要 4 个字节的内存。在 C 中,您可以要求 malloc
函数找到可用于存储 int
的 4 字节内存。 malloc(4)
。 malloc
如何告诉您将 int
放在哪里?想象一下,您从 0-
所以你不能只是改变传入的值,因为你只是得到了一个数字的副本,而不是对你可以更新的原始数字的引用。
那么什么是 C 中的数组?好吧,如果您请求 10 int
秒,malloc(sizeof(int) * 10)
的空间,那么您现在已经请求了一块 40 字节的内存。假设它在您的计算机内存中的偏移量为 1000。你只有 40 个字节。所以你可以想象前 4 个字节是第一个 int
,后四个字节是第二个 int
,依此类推。
当您将数组从 func1
传递给 func2
时,它会执行所谓的“衰减”到指针中的操作。当您将数组的名称作为参数时,唯一传递的是指向它的第一个元素的指针,该指针在您的值所在的内存中的偏移量。
所以 func1
只知道您的 int
在您的计算机内存中有 1000 个,因为它有 1000 个指针值。
当您重新分配时,它可能会说“嘿,您的数据仍为 1000”,或者可能会说“嘿,没有空间将数组从 10 int
变成 100,所以我复制了数据到一个新的偏移量,即 7000 到内存中。
它只是告诉您数据已复制到的新位置。这个信息,这个数字 7000 现在必须返回给你原来的函数。
您可以返回指针并覆盖原始函数中的指针。或者你可以在 C 中做一些非常正常的事情,但是从带有对象和引用语义等的语言中看起来很复杂。
您可以将指针传递给第一个函数中的指针所在位置,而不是在原始调用中传递指针 ( 100 ) 的值。
// returning the value example
void hello(){
int * data = malloc( sizeof(int) * 10 );
... check errors,zero memory and use 10 ints in array
data = world( data );
... use 100 ints now in array
}
int * world( int * data ){
int * data = realloc( data,sizeof(int) * 100 );
... check errors,zero new ints,and use now larger array
return data
}
你怎么知道新数组有多大?你必须在某个地方传递一个大小,因为 C 期望 你 跟踪诸如“我的数组有多大”之类的愚蠢内容。它当然不会阻止您写入 5 元素数组的第 100 个元素,并不会意外地覆盖内存中发生的任何内容(经典的缓冲区溢出是由写入超过 C 数组末尾引起的)。>
// what if we pass a pointer instead?
void hello(){
int entries = 10 ;
int * data = malloc( sizeof(int) * entries );
... error checking,zeroing memory,doing things with entries=10
world( &data,&entries );
... doing things with entries=100,and knowing because the other
... function updated the value of entries via the pointer we gave
... to it!
}
void world( int ** data,int * entries ){
int newentries = 100 ;
int * newdata = realloc( *data,sizeof(int) * newentries );
... check for NULL ( allocation failure ),zero new memory
// we overwrite the variables in the caller through the pointers
*data = newdata ;
*entries = newentries ;
}
更复杂,但功能也更多。如您所见,随着您添加指针,事情开始变得有点复杂,但功能也变得更加强大。
它们非常繁琐,毛茸茸的,你很容易因为犯错而覆盖和弄乱整个程序的内存,这就是为什么这么多人回避 C。
但它们很快!
如果操作数据有意义,您可以使用指向指针的指针,但请注意,出于某种原因,成为 ***three star programmer 是贬义的 :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。