如何使用 malloc 在 C 中创建矩阵并避免内存问题?如何使用 C99 语法将矩阵传递给函数?

2023-12-19

您有关于使用的良好指示吗?malloc为矩阵分配内存空间的函数?

这些天我看到很多编码员在需要使用矩阵时以“糟糕”的方式编码malloc来管理他们。当我这样想时,我错了吗?

我的意思是“坏”代码的一个例子如下:

int main()
{
    char **row;
    int width=80, height=24, i, j;

    row = malloc(height * sizeof(char *));
    for(i = 0; i < width; i++)
        row[i] = malloc(width * sizeof(char));

    for(i = 0; i < height; i++)
    {
        for(j = 0; j < width; j++)
        {
            row[i][j] = i*j;
        }
    }

    return 0;
}

在上面的代码中我发现至少三个问题:

  • 它强烈地碎片化记忆。

  • 它使用了超出必要的内存

  • 它使得用于矩阵的内存不连续。


有人建议我使用 C99 语法的有趣方法:

int (*matrix)[columns] = malloc(sizeof(int[rows][columns]));

现在我需要将此变量矩阵传递给以下函数:

void print_matrix2(int **m,int r,int c)
{
    int y,x;

    for(y=0;y<r;y++) {
        for(x=0;x<c;x++) {
            printf("(%2d,%2d) = %04d; ",y+1,x+1,m[y][x]);
        }
    }
}

我发现的唯一方法是更改​​原型:

void print_matrix2(int (*m)[5],int r,int c);

但我想避免 [5] 声明,我希望能够向我的函数发送我想要的任何数量的列!

如果是这样,我觉得这个 C99 改进并不是问题的最终解决方案,我认为解决矩阵管理的最好、最简单的方法是使用经典 C 语言来管理它们!


Use malloc()分配连续的内存块:

some_datatype_t* matrix = NULL;
matrix = malloc(nrows * ncols * sizeof(some_datatype_t));
if (!matrix) { 
    perror("malloc failed");
    exit(ENOMEM); 
}

编写一个函数来取消引用单元格:

some_datatype_t 
get_value_from_matrix_at_index_ij(some_datatype_t* mtx, 
                                  uint32_t ncols, 
                                  uint32_t i, 
                                  uint32_t j) 
{
    return mtx[i + i * (ncols - 1) + j];
}

或者二传手:

void
set_value_for_matrix_at_index_ij(some_datatype_t** mtx_ptr,
                                 uint32_t ncols, 
                                 uint32_t i, 
                                 uint32_t j,
                                 some_datatype_t val) 
{
    *mtx_ptr[i + i * (ncols - 1) + j] = val;
}

别忘了free()完成后你的矩阵:

free(matrix), matrix = NULL;

这是 3x4 矩阵的示例:

    0  1  2  3
  ------------
0 | 0  1  2  3
1 | 4  5  6  7
2 | 8  9 10 11

它有 3 行和 4 列(ncols = 4).

在线性化形式下,其单元格如下所示:

0 1 2 3 4 5 6 7 8 9 10 11

在某个零索引行查找单元格的内容i和列j,您可以在常数时间内计算要取消引用的索引或地址:

{1, 2} = matrix[1 + 1*3 + 2] = matrix[6]
{2, 3} = matrix[2 + 2*3 + 3] = matrix[11]
etc.

如果您想将一些有用的属性隐藏到一个干净的包中,您甚至可以将其中的大部分包装到一个struct:

typedef struct matrix {
    some_datatype_t* data;
    uint32_t nrows;
    uint32_t ncols;
} matrix_t;

然后你只需初始化并传递一个指向matrix_t多变的:

matrix_t*
init_matrix(uint32_t nrows, uint32_t ncols) 
{
    matrix_t *m = NULL;
    m = malloc(sizeof(matrix_t));
    if (!m) { /* error */ }
    m->data = NULL;
    m->data = malloc(nrows * ncols * sizeof(some_datatype_t));
    if (!m->data) { /* error */ }
    m->nrows = nrows;
    m->ncols = ncols;
    return m;
}

some_datatype_t 
get_value_from_matrix_at_index_ij(matrix_t* mtx,
                                  uint32_t i, 
                                  uint32_t j) 
{
    return mtx->data[i + i * (mtx->ncols - 1) + j];
}

void
set_value_for_matrix_at_index_ij(matrix_t** mtx_ptr,
                                 uint32_t i, 
                                 uint32_t j,
                                 some_datatype_t val) 
{
    (*mtx_ptr)->data[i + i * ((*mtx_ptr)->ncols - 1) + j] = val;
}

void
delete_matrix(matrix_t** m) 
{
    free((*m)->data), (*m)->data = NULL;
    free(*m), *m = NULL;
}

如果您使用对称方阵,则可以利用对称性并使用一半的内存。有时,如果可以删除对角线的存储(例如,相关性或其他对称统计分数),则占用的内存会少于一半。

主要是,这里的想法是思考如何编写一个在矩阵索引对之间映射的方程(i, j)和一些连续数组索引k.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 malloc 在 C 中创建矩阵并避免内存问题?如何使用 C99 语法将矩阵传递给函数? 的相关文章

  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器

随机推荐