C 中结构体和指针的 malloc

2024-04-07

假设我想定义一个表示向量长度及其值的结构,如下所示:

struct Vector{
    double* x;
    int n;
};

现在,假设我想定义一个向量 y 并为其分配内存。

struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));

我在互联网上的搜索表明我应该单独为 x 分配内存。

y->x = (double*)malloc(10*sizeof(double));

但是,我似乎为 y->x 分配了两次内存,一次为 y 分配内存,另一次为 y->x 分配内存,这似乎浪费内存。 如果让我知道编译器到底做了什么以及正确的方法是什么,我将非常感激 初始化 y 和 y->x。


不,你是not分配内存用于y->x twice.

相反,您为结构分配内存(其中包括指针)plus该指针指向的东西。

可以这样想:

         1          2
        +-----+    +------+
y------>|  x------>|  *x  |
        |  n  |    +------+
        +-----+

你实际上需要two分配(1 and 2)来存储您需要的一切。

此外,您的类型应该是struct Vector *y因为它是一个指针,所以你不应该将返回值转换为malloc in C.

它可以隐藏某些您不想隐藏的问题,并且 C 完全能够隐式转换void*返回值给任何其他指针。

当然,您可能希望封装这些向量的创建,以便更轻松地管理它们,例如在头文件中包含以下内容vector.h:

struct Vector {
    double *data;    // Use readable names rather than x/n.
    size_t size;
};

struct Vector *newVector(size_t sz);
void delVector(struct Vector *vector);
//void setVectorItem(struct Vector *vector, size_t idx, double val);
//double getVectorItem(struct Vector *vector, size_t idx);

然后,在vector.c,您拥有管理向量的实际函数:

#include "vector.h"

// Atomically allocate a two-layer object. Either both layers
// are allocated or neither is, simplifying memory checking.

struct Vector *newVector(size_t sz) {
    // First, the vector layer.

    struct Vector *vector = malloc(sizeof (struct Vector));
    if (vector == NULL)
        return NULL;

    // Then data layer, freeing vector layer if fail.

    vector->data = malloc(sz * sizeof (double));
    if (vector->data == NULL) {
        free(vector);
        return NULL;
    }

    // Here, both layers worked. Set size and return.

    vector->size = sz;
    return vector;
}

void delVector(struct Vector *vector) {
    // Can safely assume vector is NULL or fully built.

    if (vector != NULL) {
        free(vector->data);
        free(vector);
    }
}

通过像这样封装向量管理,您可以确保向量要么完全构建,要么根本不构建 - 有no它们有可能是半建成的。

它还允许您将来完全更改底层数据结构而不影响客户端。例如:

  • 如果你想让它们成为稀疏数组以牺牲空间和速度。
  • 如果您希望数据在更改时保存到持久存储中。
  • 如果您希望确保所有向量元素都初始化为零。
  • if you wanted to separate the vector size from the vector capacity for efficiency(1).

您还可以根据需要添加更多功能,例如安全设置或获取向量值(请参阅标题中的注释代码)。

For example, you could (as one option) silently ignore setting values outside the valid range and return zero if getting those values. Or you could raise an error of some description, or attempt to automatically expand the vector under the covers(1).


在使用向量方面,一个简单的例子如下(非常基本)main.c

#include "vector.h"

#include <stdio.h>

int main(void) {
    Vector myvec = newVector(42);
    myvec.data[0] = 2.718281828459;
    delVector(myvec);
}

(1) That potential for an expandable vector bears further explanation.

许多向量实现将容量与大小分开。前者是在需要重新分配之前可以使用多少个元素,后者是实际的向量大小(始终

扩展时,您通常希望以不进行太多操作的方式进行扩展,因为这可能是一项昂贵的操作。例如,您可以添加比严格必要的多 5% 的元素,这样,在循环中连续添加一个元素时,就不必为每一项重新分配。

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

C 中结构体和指针的 malloc 的相关文章

随机推荐

  • 如何在 PostgreSQL 中的换行符上将一个值拆分为多行?

    我有一个名为BookInfo具有以下结构 id book name description 1 book 1 harry potter Part 2 2 我怎样才能分割该行 id 1 在换行符上分成多行 以便harry n potter n
  • iOS 14 - 如何以编程方式打开默认邮件应用程序?

    使用 iOS14 用户可以将不同的电子邮件客户端应用程序设置为默认值 有没有办法以编程方式打开选定的默认邮件应用程序 Using mailto URL 将默认邮件应用程序设置为 Gmail 后 不执行任何操作 显然你必须添加mailto t
  • 禁用 eclipselink 缓存和查询缓存 - 不起作用?

    我正在使用 eclipselink JPA 和数据库 该数据库也在我的应用程序外部进行更新 因此 我想每隔几秒钟查询一些表 即使我尝试禁用缓存和查询缓存 我也无法使其工作 例如 EntityManagerFactory entityMana
  • Google Maps Api 直线(最短)路线

    我目前正在尝试找到一种使用 Google Maps Api V3 获得直线路线的方法 我已经设法使用地理编码和方向服务来获取从 A 点到 B 点的路线 包括两条替代路线 我还尝试过 禁止高速公路 和 禁止通行费 但似乎没有什么可以完全解决这
  • 无法使用命令行解释器

    我尝试在 php 解释器中执行简单的 php 代码 当我执行命令时php a我收到消息 启用交互模式 没有任何地方可以输入 php 但我可以通过命令执行php代码php r 例如 php r echo Hello stackoverflow
  • zclip 在 jquery ui 非活动选项卡中不起作用

    我在用zclip http www steamdev com zclip 在我的 asp net 网页上的 jQuery UI 选项卡中的 jQuery UI 对话框中 它在第一个处于活动状态的选项卡中效果很好 但当我将其添加到第二个选项卡
  • 如何从 Git 存储库中删除文件?

    我怎样才能删除 file1 txt 从我的存储库 Use git rm https git scm com docs git rm 如果您想从 Git 存储库中删除该文件和文件系统 use git rm file1 txt git comm
  • SQL 将一列的值分组到另一列

    SQL 中是否有某种 聚合 函数可以将值转换为列表 一个示例可能是以下形式的表格 game id player score 1 fred 2 1 tom 1 2 fred 3 2 tom 4 我想要返回的是一个如下所示的表 player s
  • 在 postgres 中分割人名的最简单方法?

    考虑一个包含人类全名的表 create table names full name varchar not null insert into names full name values Jane Marie Doe John Doe 在
  • 在Python中分割句子

    我正在尝试将句子分成单词 words content lower split 这给了我这样的单词列表 evening and there was morning the first day 并使用以下代码 def clean up list
  • 使用表单方法将隐藏输入值设置为要提交的 blob

    我正在尝试提交一个表单 其中一个 blob 附加到一个隐藏的输入标签 如下所示
  • 增加溢出宽度以调整滚动条

    当滚动条可见时 我应该使用什么 CSS 来使 div 调整其宽度 这是场景 我有一个 div 和子元素 div ul li li li li li li ul ul li li li li li li ul div 我想在溢出时自动调整滚动
  • 带注释的代码风格[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我无法在两者之间做出决定 MyAnnotation param1 paramval public void foo and MyAnnotati
  • 将 CSS 属性排序为任意顺序?

    我想以编程方式将样式表中的所有声明 属性 不是声明块本身 而是每个块内的各个声明 排序为任意顺序 我已经能够在网上找到几种按字母顺序排序声明的方法 或者按字母顺序反向排序 甚至按字符串长度排序 但这对我来说没有帮助 因为这些排序方法本质上是
  • WPF - 为什么 ContextMenu 项目适用于 ListBox 而不是 ItemsControl?

    列表中的项目有上下文菜单 上下文菜单项绑定到路由命令 如果列表控件是一个 则上下文菜单项可以正常工作ListBox 但一旦我将其降级为ItemsControl它不再起作用了 具体来说 菜单项始终呈灰色 这CanExecute回调在我的Com
  • N Boost Interval_set 的组合

    我的服务在 4 个不同的地点出现中断 我将每个位置的中断建模为 Boost ICL Interval set 我想知道何时至少有 N 个地点发生主动中断 因此 以下这个答案 https stackoverflow com a 9430993
  • Typescript 编译错误:类型“Node”上不存在属性“classList”

    Windows 7 x64 使用 typescript 1 5 beta 使用 gulp typescript 2 7 7 进行编译 出现错误 由于语句 类型 Node 上不存在属性 classList document getElemen
  • 如何修复“OSError:[WinError 193] %1 不是有效的 Win32 应用程序”

    我正在努力与熊猫相处 我正在使用 Thonny 作为 IDLE 来学习 Python 我在 cmd 中使用 pip 命令安装了 pandas 不知何故 我无法在 IDLE 中导入 pandas 方法 因此我通过设置将其添加为包 问题是 当我
  • 自动在所有方法上设置断点

    有没有一种方法可以自动在 eclipse idea 中对给定类中的所有方法设置断点 在大纲视图 Eclipse 中 您可以选择所有方法 右键单击并选择 切换方法断点
  • C 中结构体和指针的 malloc

    假设我想定义一个表示向量长度及其值的结构 如下所示 struct Vector double x int n 现在 假设我想定义一个向量 y 并为其分配内存 struct Vector y struct Vector malloc size