首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在C中按值传递结构而不是传递指针有什么缺点吗?

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

Stack Overflow用户
提问于 2008-10-02 11:21:13
回答 7查看 91.2K关注 0票数 173

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

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

当用作返回值时,它可能更有趣。C语言只有一个函数返回值,但是你经常需要几个返回值。因此,一个简单的解决方案是将它们放在一个结构中,然后返回该结构。

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

由于我在这里所说的内容可能对每个人都不明显,因此我将举一个简单的例子。

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

代码语言:javascript
复制
void examine_data(const char *ptr, size_t len)
{
    ...
}

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

这不是问题。唯一的问题是,你必须与你的同事达成一致,参数的顺序应该是这样的,所以你在所有函数中使用相同的约定。

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

代码语言:javascript
复制
char *get_data(size_t *len);
{
    ...
    *len = ...datalen...;
    return ...data...;
}
size_t len;
char *p = get_data(&len);

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

因此,我提出的解决方案是简单的struct

代码语言:javascript
复制
struct blob { char *ptr; size_t len; }

示例可以像这样重写:

代码语言:javascript
复制
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接受指向结构blob的指针,但我不明白为什么。它仍然有一个指针和一个整数,它们放在一起就更清楚了。在get_data的情况下,不可能以我前面描述的方式搞乱,因为没有长度的输入值,并且必须有返回的长度。

EN

回答 7

Stack Overflow用户

发布于 2008-10-02 11:39:51

对于较小的结构(如point,rect),通过值传递是完全可以接受的。但是,除了速度之外,还有另一个原因需要注意通过值传递/返回大型结构:堆栈空间。

许多C编程是针对嵌入式系统的,在嵌入式系统中,内存非常宝贵,堆栈的大小可以用KB甚至Bytes来度量……如果您通过值传递或返回结构,则这些结构的副本将被放置在堆栈中,这可能会导致this site以...

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

票数 221
EN

Stack Overflow用户

发布于 2008-10-02 13:04:04

到目前为止,这里的人们忘记提到的一件事(或者我忽略了它)是,结构通常有一个填充!

代码语言:javascript
复制
struct {
  short a;
  char b;
  short c;
  char d;
}

每一个字符是1个字节,每个短字符是2个字节。结构有多大?不,它不是6个字节。至少不是在任何更常用的系统上。问题是,对齐不是恒定的,它依赖于系统,所以相同的结构在不同的系统上会有不同的对齐方式和大小。

这种填充不仅会进一步吞噬你的堆栈,而且还增加了无法提前预测填充的不确定性,除非你知道你的系统填充是如何的,然后查看你的应用程序中的每个结构并计算它的大小。传递一个指针会占用可预测的空间量--这是不确定的。指针的大小对于系统是已知的,它总是相等的,无论结构看起来是什么样子,并且指针大小总是以一种对齐的方式选择的,不需要填充。

票数 16
EN

Stack Overflow用户

发布于 2008-10-02 11:35:23

简单解决方案是将错误代码作为返回值返回,其他所有内容都作为函数中的参数返回,

这个参数当然可以是一个结构,但是看不到通过值传递这个参数有什么特别的好处,只是发送了一个指针。

通过值传递结构是危险的,你需要非常小心你传递的是什么,记住在C中没有复制构造函数,如果结构参数之一是一个指针,指针值将被复制,这可能会非常混乱和难以维护。

只是为了完整的回答(完全归功于Roddy )堆栈的使用是另一个不通过值传递结构的原因,相信我调试堆栈溢出是真正的皮塔。

重播评论:

通过指针传递struct,这意味着某个实体拥有此对象的所有权,并且完全了解应该释放什么以及何时释放。按值传递struct会创建对struct内部数据的隐藏引用(指向另一个结构的指针等)。)这很难维护(有可能,但为什么呢?)

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/161788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档