如何通过另一个函数中的一个函数调整创建的数组的大小?

如何解决如何通过另一个函数中的一个函数调整创建的数组的大小?

我在一个函数(比如 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- 开始对计算机内存的字节进行编号。 Malloc 返回存储内存的偏移量。它永远不会移动或改变大小或其他任何东西。它只是内存中某个特定偏移量的四个字节。如果它是 100 字节,你的指针就是 100。如果它是 1,000,000 字节,那将是你的指针值。要记住的重要一点是指针是。它们是一个数字,表示您的数据在内存中的位置。如果您传递一个指针,您就是在将该偏移量传递到内存中。那个号码。就像你想要一个整数一样。

所以你不能只是改变传入的值,因为你只是得到了一个数字的副本,而不是对你可以更新的原始数字的引用。

那么什么是 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 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res