在 C 中按值传递结构而不是传递指针有什么缺点吗?

2023-12-06

在 C 中按值传递结构而不是传递指针有什么缺点吗?

如果结构体很大,显然会存在复制大量数据的性能问题,但对于较小的结构体,它基本上应该与将多个值传递给函数相同。

当用作返回值时,它可能会更有趣。 C 函数只有单个返回值,但您通常需要多个返回值。因此,一个简单的解决方案是将它们放入一个结构中并返回该结构。

有什么理由支持或反对吗?

由于大家可能不太清楚我在这里所说的内容,所以我举一个简单的例子。

如果您使用 C 语言编程,您迟早会开始编写如下所示的函数:

void examine_data(const char *ptr, size_t len)
{
    ...
}

char *p = ...;
size_t l = ...;
examine_data(p, l);

这不是问题。唯一的问题是,您必须与同事同意参数的顺序,以便您在所有函数中使用相同的约定。

但是当您想要返回相同类型的信息时会发生什么?你通常会得到这样的结果:

char *get_data(size_t *len);
{
    ...
    *len = ...datalen...;
    return ...data...;
}
size_t len;
char *p = get_data(&len);

这工作得很好,但问题更多。返回值就是返回值,但在此实现中它不是。从上面无法看出该函数get_data不允许查看什么len指着。并且没有任何东西可以让编译器检查是否确实通过该指针返回了值。因此,下个月,当其他人在没有正确理解代码的情况下修改代码时(因为他没有阅读文档?),它会在没有人注意到的情况下被破坏,或者开始随机崩溃。

所以,我提出的解决方案是简单的结构

struct blob { char *ptr; size_t len; }

这些例子可以重写如下:

void examine_data(const struct blob data)
{
    ... use data.tr and data.len ...
}

struct blob = { .ptr = ..., .len = ... };
examine_data(blob);

struct blob get_data(void);
{
    ...
    return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();

出于某种原因,我认为大多数人会本能地做出examine_data获取一个指向 struct blob 的指针,但我不明白为什么。它仍然得到一个指针和一个整数,只是它们在一起更加清晰。并且在get_data在这种情况下,不可能像我之前描述的那样搞乱,因为没有长度的输入值,并且必须有一个返回的长度。


对于小型结构(例如点、矩形),按值传递是完全可以接受的。但是,除了速度之外,还有一个原因让您应该小心按值传递/返回大型结构:堆栈空间。

许多 C 编程都是针对嵌入式系统的,其中内存非常宝贵,堆栈大小可能以 KB 甚至字节为单位...如果您按值传递或返回结构,这些结构的副本将被放置在堆栈,可能会导致以下情况这个网站得名于...

如果我看到一个应用程序似乎有过多的堆栈使用,那么按值传递的结构是我首先寻找的东西之一。

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

在 C 中按值传递结构而不是传递指针有什么缺点吗? 的相关文章

  • 如何在 Visual Studio 2010 中增强 XAML 设计器?

    当我使用 XAML 设计器时 进入设计器和退出设计器是如此困难和缓慢 当我这样做时 Visual Studio 卡了一段时间 有什么方法可以增强 XAML 设计器和编辑器吗 Ant 保存 XAML 文件时非常慢 这通常意味着您可能有复杂的
  • c和java语言中的换行符

    现在行分隔符取决于系统 但在 C 程序中我使用 n 作为行分隔符 无论我在 Windows 还是 Linux 中运行它都可以正常工作 为什么 在java中 我们必须使用 n 因为它与系统相关 那么为什么我们在c中使用 n 作为新行 而不管我
  • 启动时出现 OData v4 错误:找不到段“Whatever”的资源

    我正在构建新的 v4 服务 一切进展顺利 直到我为新模型 实体添加了新控制器 并在启动站点进行测试运行时收到此错误 控制器似乎编码正确 就像其他控制器一样 控制器 CustomersOData 中的操作 GetFeed 上的路径模板 Cus
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • 如何修复此错误“GDI+ 中发生一般错误”?

    从默认名称打开图像并以默认名称保存 覆盖它 我需要从 Image Default jpg 制作图形 将其放在 picturebox1 image 上并在 picurebox1 上绘制一些图形 它有效 这不是我的问题 但我无法保存 pictu
  • 将内置类型转换为向量

    我的 TcpClient 类接受vector
  • 如何从 .resx 文件条目获取注释

    资源文件中的字符串有名称 值和注释 The ResXResourceReader类让我可以访问名称和值 有办法看评论吗 你应该能够得到Comment via ResXDataNode class http msdn microsoft co
  • 如何访问另一个窗体上的ListView控件

    当单击与 ListView 所在表单不同的表单中的按钮时 我试图填充 ListView 我在 Form1 中创建了一个方法以在 Form2 中使用 并将参数传递给 Form1 中的方法 然后填充 ListView 当我调试时 我得到了传递的
  • 将 System.Windows.Input.KeyEventArgs 键转换为 char

    我需要将事件参数作为char 但是当我尝试转换 Key 枚举时 我得到的字母和符号与传入的字母和符号完全不同 如何正确地将密钥转换为字符 这是我尝试过的 ObserveKeyStroke this new ObervableKeyStrok
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 如何在 C# 中定义文本框数组?

    您好 当我在 Windows 申请表上创建文本框时 我无法将其命名为 box 0 box 1 等 我这样做的目的是因为我想循环使用它们 其实我发现TextBox array firstTextBox secondTextBox 也有效
  • 如何将整数转换为 void 指针?

    在 C 中使用线程时 我面临警告 警告 从不同大小的整数转换为指针 代码如下 include
  • PlaySound 可在 Visual Studio 中运行,但不能在独立 exe 中运行

    我正在尝试使用 Visual Studio 在 C 中播放 wav 文件 我将文件 my wav 放入项目目录中并使用代码 PlaySound TEXT my wav NULL SND FILENAME SND SYNC 我按下播放按钮 或
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 使用 Moq 使用内部构造函数模拟类型

    我正在尝试模拟 Microsoft Sync Framework 中的一个类 它只有一个内部构造函数 当我尝试以下操作时 var fullEnumerationContextMock new Mock
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • 如何对 Web Api 操作进行后调用?

    我创建了一个 Web API 操作 如下所示 HttpPost public void Load string siteName string providerName UserDetails userDetails implementat
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 检查Windows控制台中是否按下了键[重复]

    这个问题在这里已经有答案了 可能的重复 C 控制台键盘事件 https stackoverflow com questions 2067893 c console keyboard events 我希望 Windows 控制台程序在按下某个

随机推荐

  • 方向改变时相机出现问题

    我正在开发一个应用程序 当设备方向从横向变为纵向或反之亦然时 该应用程序会调用不同的活动 横向模式的活动是增强现实活动 因此我使用相机向用户展示周围环境 但是 当我尝试返回纵向时 应用程序崩溃并显示以下错误 08 17 16 05 42 6
  • 在 Django 中为两种类型的用户子类 AbstractUser

    我正在 Django 1 5 中开发一个学校数据库系统 并计划拥有许多不同的用户类型 学生 员工 家长 这些用户类型是 AbstractUser 的子类 实际上是 AbstractUser 的另一个抽象子类 我只是试图将外部开发的应用程序添
  • QT“没有这样的插槽”错误[重复]

    这个问题在这里已经有答案了 这是我的类定义 hpp 文件的一部分 class RenderGraphFrame public QGLWidget public RenderGraphFrame QWidget parent private
  • 如何递归计算列表中的项目数

    我希望递归地计算列表中的项目 例如 我列出了几个列表 a b c h b d c e f h 我试图找到一种方法来找出列表 a 的长度 但是在列表 a 中 我有 b c 和 h 因此我的函数然后进入列表 b 并计算那里的元素数量 然后列表
  • 在 Windows 10 上为 PyPy3 安装 numpy 时出现问题

    我在尝试在 Windows 10 计算机上安装 pypy3 的 numpy 时遇到问题 由于我无法判断这个问题是源于我的 pypy3 安装还是其他原因 所以我在这里描述了迄今为止我所遵循的所有步骤 正如官方所示下载页面 I have 下载并
  • git pull 是否总是创建合并提交?

    Does git pull总是创建合并提交 如果我有一个我更新的功能分支git pull r master 然后我切换到 master 并执行git pull feature branch我不think我得到一个合并提交 你有一个关于 gi
  • 如何像模拟橡皮擦效果一样用线条路径绘制CALayer?

    我想用触摸事件模拟橡皮擦效果 以显示顶部某块后面的图像 例如灰色 像这样的东西 我已经找到解决方案很长时间了 但我不能做得很好 以下是我的自定义视图代码 自定义视图 m id initWithCoder NSCoder aDecoder i
  • Val 在 Scala 中的行为

    我在尝试从 Eclipse 执行以下代码时收到错误 因为我无法重新分配 Val 对吧 object Test def main args Array String val tempVal 100 val checkval if tempVa
  • 在 javafx 中创建图像覆盖蒙版

    我正在尝试做一件简单的事情 我有一个二值图像 我想要的只是将二值图像叠加在彩色图像上 但是二值图像中的白色像素应该是红色的 黑色像素应该是透明的 我已经习惯了 JavaFx 但我还是坚持使用这个 我知道我可以通过使用 PixelReader
  • Raspberry ALSA 声音输出/输入从机

    我正在尝试设置一台设备用于播放 另一台设备用于捕获 我的nano etc asound conf有这个 pcm default type asym playback pcm plughw 1 1 capture pcm plughw 1 0
  • Celery / Django 单个任务运行多次

    我面临一个问题 我将任务放入队列中并且它正在运行多次 从 celery 日志中我可以看到同一个工作人员正在运行该任务 2014 06 06 15 12 20 731 INFO MainProcess Received task input
  • 使用spring进行Java注解扫描

    我有几个类需要用名称进行注释 因此我将注释定义为 Retention RetentionPolicy RUNTIME Target ElementType TYPE public interface JsonUnmarshallable p
  • Ruby ** 双星运算符

    Ruby 中的 运算符是什么 代码片段 1 5 gt 1 43 67 gt 2769405330765659902380925787724104201956901039505346829415349981622358603023818638
  • IE 对 HTML5 文档类型属性选择器的支持

    w3school 关于属性选择器的章节指出 仅当指定 DOCTYPE 时 IE7 和 IE8 才支持属性选择器 IE7 和 IE8 无法识别 HTML5 文档类型 对吗 那么 这是否意味着如果我使用 HTML5 文档类型 IE7 和 IE8
  • Selenium 与 Python-unittest - 测试返回进程已完成,退出代码为 0,并且不执行任何操作

    有人可以帮助我理解为什么执行以下代码 但没有执行任何操作吗 返回代码为 0 但浏览器未打开或未执行任何操作 值得一提的是 setUp 方法已在其他模块中以相同的方式配置 并且工作正常 请查看最后的回复 import unittest fro
  • 如何翻译 Blazor 组件和 App.razor 中的字符串?

    我想本地化共享组件的字符串 例如 NavMenu razor 或 App razor 页面 我成功地按照中所述翻译了我的页面中的内容 NET Core 通用指令还有更多特定 Blazor 文档 创建具有正确名称的资源文件 例如 PageNa
  • 如何在 thymeleaf 中包含 message.properties

    I am using spring boot with thymeleaf This is my project structure 这是我的应用程序开始课程 EnableAutoConfiguration Configuration Co
  • 查询 documentdb 中的子字段

    例如 我有以下用于收集 交付的文档 doc docid 15 deliverynum 123 text txxxxxx date 2019 07 18T12 37 58Z docid 16 deliverynum 456 text txxx
  • 如何在sqlite中使用填充连接字符串

    我的 sqlite 表中有三列 Column1 Column2 Column3 A 1 1 A 1 2 A 12 2 C 13 2 B 11 2 我需要选择Column1 Column2 Column3 e g A 01 0001 我想用一
  • 在 C 中按值传递结构而不是传递指针有什么缺点吗?

    在 C 中按值传递结构而不是传递指针有什么缺点吗 如果结构体很大 显然会存在复制大量数据的性能问题 但对于较小的结构体 它基本上应该与将多个值传递给函数相同 当用作返回值时 它可能会更有趣 C 函数只有单个返回值 但您通常需要多个返回值 因