在推出自己的结构时提供辅助函数

2023-12-26

如果我正在开发一个 C 共享库并且我有自己的结构。为了使库使用者更容易对这些结构实例进行常见操作,我可以在结构本身内部提供指向此类函数的函数指针吗?这是一个好的做法吗?使用不同参数并行调用实用函数等多线程处理是否会出现问题?

我知道它更接近 C++ 类,但我希望坚持使用 C 并学习如何使用过程语言而不是 OOP 来完成它。

举个例子

typedef struct tag tag;
typedef struct my_custom_struct my_custom_struct;

struct tag
{
    // ...
};

struct my_custom_struct
{
    tag *tags;
    my_custom_struct* (*add_tag)(my_custom_struct* str, tag *tag);  
};

my_custom_struct* add_tag(my_custom_struct* str, tag *tag)
{
    // ...
}

其中 add_tag 是一个帮助器,它设法将标签添加到 *str 内的标签列表中。 我在 libjson-c 中看到了这种模式,如下所示-http://json-c.github.io/json-c/json-c-0.13.1/doc/html/structarray__list.html http://json-c.github.io/json-c/json-c-0.13.1/doc/html/structarray__list.html。里面给出了一个函数指针array_list帮助释放它。


为了使库更容易对这些结构实例进行常见操作 消费者,我可以提供内部此类函数的函数指针吗 结构本身?

可以为您的结构赋予函数指针成员,指向其参数包括指向结构类型的指针的函数类型,并且旨在或多或少像 C++ 实例方法一样使用,或多或少如问题中所示。

这是一个好的做法吗?

TL;DR:没有。

您将遇到的第一个问题是正确初始化这些指针成员。尽管名称对应,结构实例中的函数指针不会自动初始化为指向特定函数。除非您使结构类型不透明,否则用户可以(毫无疑问有时will)声明实例而不调用您为此目的提供的任何构造函数模拟函数,然后就会发生混乱。

如果您确实使结构不透明(这毕竟不是一个坏主意),那么无论如何您都需要非成员函数,因为您的用户将无法直接访问函数指针。也许是这样的:

struct my_custom_struct *my_add_tag(struct my_custom_struct *str, tag *tag) {
    return str->add_tag(str, tag);
}

但如果你要提供这一点,那么额外的间接层有什么意义呢? (回答only这样做的充分理由是,在不同的实例中,函数指针可以指向不同的函数。)

如果您不使结构变得不透明,则类似的情况也适用。那么您可能会假设用户会(更)直接调用

str->add_tag(str, tag);

但到底是什么让这变得如此便利?

add_tag(str, tag);

?

所以总的来说,不,我不认为这种方法总体上是一个好的做法。在有限的情况下,按照这些思路做一些事情可能是有意义的,但不作为一般的图书馆惯例。

会不会有问题 关于调用实用程序函数的多线程 与不同的论点平行等等?

与以任何其他方式指定的函数一样,除非函数指针本身被修改。

我知道它更接近 C++ 类,但我希望坚持使用 C 并学习如何用过程语言来完成它,而不是 面向对象编程。

如果您想学习 C 语言习惯和约定,请务必这样做。你所描述的不是一类。 C 代码和库绝对可以使用 OO 原则(例如封装)进行设计,在某种程度上甚至是多态性,但通常不会通过您描述的机制来实现。这个答案涉及到一些方法are用于目的。

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

在推出自己的结构时提供辅助函数 的相关文章

  • VLC 媒体播放器有 C# 界面吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否可以使用 C 控制台应用程序中的包装器从 VLC 播放中当前播放的文件中读取曲目统计信息 时间 标
  • C# 静态类型不能用作参数

    public static void SendEmail String from String To String Subject String HTML String AttachmentPath null String Attachme
  • 如何从字符串中提取子字符串直到遇到第二个空格?

    我有一个像这样的字符串 o1 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 如何仅提取 o1 1232 5467 要提取的字符数并不总是相同 因此 我只想提取直到遇到
  • 使用 ADAL v3 使用 ClientID 对 Dynamics 365 进行身份验证

    我正在尝试对我们的在线 Dynamics CRM 进行身份验证以使用可用的 API 我能找到的唯一关于执行此操作的官方文档是 https learn microsoft com en us dynamics365 customer enga
  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • EntityHydrate 任务失败

    我最近安装了 Visual Studio 11 Beta 和 Visual Studio 2010 之后 我无法在 Visual Studio 2010 中构建依赖于 PostSharp 的项目 因此我卸载了 Visual Studio 1
  • Boost ASIO 串行写入十六进制值

    我正在使用 ubuntu 通过串行端口与设备进行通信 所有消息都必须是十六进制值 我已经在 Windows 环境中使用白蚁测试了通信设置 并得到了我期望的响应 但在使用 Boost asio 时我无法得到任何响应 以下是我设置串口的方法 b
  • Selenium - C# - Webdriver - 无法找到元素

    在 C 中使用 selenium 我试图打开浏览器 导航到 Google 并找到文本搜索字段 我尝试下面的 IWebDriver driver new InternetExplorerDriver C driver Navigate GoT
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • Android NDK 代码中的 SIGILL

    我在市场上有一个 NDK 应用程序 并获得了有关以下内容的本机崩溃报告 SIGILL信号 我使用 Google Breakpad 生成本机崩溃报告 以下是详细信息 我的应用程序是为armeabi v7a with霓虹灯支持 它在 NVIDI
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 测量进程消耗的 CPU 时钟

    我用 C 语言编写了一个程序 它是作为研究结果创建的程序 我想计算程序消耗的确切 CPU 周期 精确的循环次数 知道我怎样才能找到它吗 The valgrind tool cachegrind valgrind tool cachegrin
  • 如何在 Javascript 中连接 C# ActiveX 事件处理程序

    我尝试使用几个代码片段将 ActiveX 对象与 Javascript 事件处理程序挂钩 我无法确定为什么事件处理程序没有被调用 带有项目的 Github 存储库 https github com JesseKPhillips Csharp
  • 如何在多线程应用程序中安全地填充数据并 Refresh() DataGridView?

    我的应用程序有一个 DataGridView 对象和一个 MousePos 类型的列表 MousePos 是一个自定义类 它保存鼠标 X Y 坐标 类型为 Point 和该位置的运行计数 我有一个线程 System Timers Timer
  • SQLAPI++ 的免费替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有任何免费 也许是开源 的替代品SQLAPI http www sqlapi com 这个库看起来
  • 当Model和ViewModel一模一样的时候怎么办?

    我想知道什么是最佳实践 我被告知要始终创建 ViewModel 并且永远不要使用核心模型类将数据传递到视图 这就说得通了 让我把事情分开 但什么是Model 和ViewModel一模一样 我应该重新创建另一个类还是只是使用它 我觉得我应该重
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 任何人都可以清楚地告诉如何在不使用像 这样的预定义函数的情况下找到带有小数值或小数值的指数吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 例如 2 0 5 1 414 所以想要 我是 c 的新手 所以请解释简单的逻辑 如果不是复杂的逻辑也足够了 在数学中 从整数取幂到实数
  • winform c# 中的弹出窗口

    我正在开发一个需要弹出窗口的项目 但问题是我还希望能够通过表单设计器在此弹出窗口中添加文本框等 所以基本上我有一个按钮 当您单击它时 它将打开我在表单设计器中设计的另一个窗口 我一直在谷歌搜索 但还没有找到我需要的东西 所以我希望你们能帮助
  • 如果找不到指定的图像文件,显示默认图像的最佳方式?

    我有一个普通的电子商务应用程序 我将 ITEM IMAGE NAME 存储在数据库中 有时经理会拼错图像名称 为了避免 丢失图像 IE 中的红色 X 每次显示产品列表时 我都会检查服务器中是否有与该产品相关的图像 如果该文件不存在 我会将其

随机推荐

  • SonarQube 抱怨:要么记录或重新抛出此异常

    在将代码与 Maven 集成后 我正在运行 SonarQube 5 进行代码质量检查 声纳抱怨我应该 记录或重新抛出此异常 在下面的代码中 public static Date convertStringtoDate String stri
  • 使用 Spring AOP 时,在单个连接点上绑定参数的多个 around 建议会导致错误

    我在一个方法上写了 2 个注释 并写了 2 个周围建议来处理每个注释值 连接点方法是这样的 CacheFetch cacheName CacheManager CACHE DATASOURCE INFO TenantAware method
  • 如何从 SQL 注入攻击中删除帖子中的脚本?

    我有一个插件 使我的 WordPress 网站容易受到 SQL 注入攻击 此后我锁定了我的网站并删除了所有 Wordpress 文件 然后重新安装了 Wordpress 该插件也已被删除 不幸的是 我现在所有 2503 个帖子都安装了以下示
  • 当输入列表为空时删除 JXLS 中的模板行

    我正在使用 JXLS 填充 Excel 电子表格模板 有时 一个输入 列表 是空的 发生这种情况时 使用此列表的模板字段将以完整的 JXLS 标志显示在填充的电子表格中 例如 someList someValue 有问题的字段都在一行中 扩
  • 角度 2 中的指令执行顺序

    如果我有一个带有单击处理程序和自定义属性指令的简单按钮 如下所示
  • 如何使用所需信息呈现表单字段

    有没有什么聪明的方法可以让 django 表单在所需字段后渲染带有星号的字段 或者提供一些其他聪明的方法来标记必填字段 如果我已经按照表单中的要求设置了字段 我不想在模板中再次执行此操作 从 Django 1 2 开始 如果您的表单有一个名
  • Xcode 链接器错误:对于架构 x86_64 文件太小

    我正在 Xcode 中开发一个应用程序 当我尝试构建时 出现此错误 ld in Users theodore Library Developer Xcode DerivedData Tower bkpdifuqssebjdgurzmtirb
  • 如何处理java中“死存储到局部变量”的错误?

    我写了一个简单的测试代码 这是一个圆圈 我想大多数人都能想象到什么是圆类 所以我就不贴了 在测试代 码中 我尝试使用无效点测试圆构造函数 并假设抛出异常 但出现了一个错误 上网查了一下 还是不知道如何解决 有人可以帮助我吗 谢谢 代码信息
  • 日期时间值不正确:“2012-07-14 23:00:00”

    我在使用 Python MySQL 处理日期时间格式时遇到一些问题 我使用以下脚本 由 Python 字典提供 计算日期时间 tempDate str eachday get date get year zfill 4 str eachda
  • #include 导致很多语法错误

    我的程序使用 Qt 和 OpenGL 它在 Linux 和 Mac 下都能正确编译 在Windows上编译时 我需要 include windows h才能使用OpenGL 代码如下 if defined WIN32 defined WIN
  • 不能需要全局 npm 模块

    我有以下问题 我安装 uuidnpm install g uuid 当我尝试运行以下代码时 var uuid require uuid console log uuid v1 抛出异常 module js 339 throw err Err
  • std::vector 和 C 风格数组

    我正在尝试OpenCL http www khronos org opencl 提高我们软件的速度 我们经常使用映射 为了简化 将映射表示为 std vector OpenCL API 采用原始 C 风格指针作为参数 例如上述情况中的 in
  • 如何设置PowerShell的默认目录?

    有没有办法更改 PowerShell 默认位置 如何设置PowerShell的默认工作目录 创建一个PowerShell 简介 https learn microsoft com en us powershell module micros
  • com.microsoft.sqlserver.jdbc.SQLServerException:MSI 令牌失败:无法从 MSI 端点获取令牌

    我想使用应用服务 API Java 和 MSI 托管服务身份 身份验证来访问 Azure SQL 数据库 我试图找出如何从适用于 Java 的 Azure 应用服务将 Azure sql 与 MSI 连接 这是我正在使用的连接字符串 jdb
  • 脚本脚本需要刷新页面才能运行吗?

    该脚本有助于在线商店的结帐过程 除了需要刷新页面以使程序最初运行之外 一切正常 我想知道这是否是缓存问题 因为它适用于以前查看过的其他产品 我也尝试修补 run at无济于事 我正在使用脚本式的扩展 它是一个独立的 js file User
  • 如何在 Node.js 中渲染 EJS 模板文件?

    我正在使用 Node js 并尝试呈现 EJS 模板文件 我弄清楚了如何渲染字符串 var http require http var ejs require ejs var server http createServer functio
  • 如何查看jOOQ执行的SQL语句?

    我使用 jOOQ 从表中查询 插入 更新数据 有没有办法查看JOOQ执行的SQL语句 查找您的日志配置文件 或创建一个 并设置该类的日志级别org jooq tools LoggerListener as debug or trace 例如
  • 在 netty 通道上设置套接字超时

    我有一个 netty 通道 我想在底层套接字上设置超时 默认设置为 0 超时的目的是 如果 15 分钟内没有发生任何事情 则未使用的通道将被关闭 虽然我没有看到任何配置可以这样做 而且套接字本身也对我隐藏 Thanks 如果使用ReadTi
  • 带命名空间的 xpath

    我正在尝试在 php SimpleXML 中使用 xpath 和 xml 文件 其中以下是相关片段
  • 在推出自己的结构时提供辅助函数

    如果我正在开发一个 C 共享库并且我有自己的结构 为了使库使用者更容易对这些结构实例进行常见操作 我可以在结构本身内部提供指向此类函数的函数指针吗 这是一个好的做法吗 使用不同参数并行调用实用函数等多线程处理是否会出现问题 我知道它更接近