结构可以通过值传递/返回,也可以通过C中的引用(通过指针)传递/返回.
普遍的共识似乎是,在大多数情况下,前者可以适用于没有惩罚的小结构.请参阅是否存在直接返回结构的良好做法?和是否有任何缺点由值用C传递结构,而不是传递指针?
从速度和清晰度的角度来看,避免取消引用可能是有益的.但什么算小?我想我们都同意这是一个小结构:
struct Point { int x, y; };
Run Code Online (Sandbox Code Playgroud)
我们可以通过相对有罪不罚的价值来传递:
struct Point sum(struct Point a, struct Point b) {
return struct Point { .x = a.x + b.x, .y = a.y + b.y };
}
Run Code Online (Sandbox Code Playgroud)
那个Linux task_struct是一个大型结构:
我们希望不惜一切代价避免使用堆栈(特别是那些8K内核模式堆栈!).但是什么是中等的?我假设小于寄存器的结构是好的.但那些呢?
typedef struct _mx_node_t mx_node_t;
typedef struct _mx_edge_t mx_edge_t;
struct _mx_edge_t {
char symbol;
size_t next;
};
struct _mx_node_t {
size_t id;
mx_edge_t edge[2];
int action;
};
Run Code Online (Sandbox Code Playgroud)
确定结构是否足够小以确定是否可以安全地通过值传递(缺少某些深度递归等情有可原的情况),最好的经验法则是什么?
最后请不要告诉我需要个人资料.当我太懒的时候,我要求使用启发式方法/它不值得进一步调查.
编辑:到目前为止,根据答案我有两个后续问题:
如果结构实际上小于指向它的指针怎么办? …
直到今天,我一直认为正确的编译器会自动将struct pass-by-value转换为pass-by-reference,如果struct足够大,后者会更快.据我所知,这似乎是一个简单的优化.然而,为了满足我对这是否真的发生的好奇心,我在C++和D中创建了一个简单的测试用例,并查看了GCC和Digital Mars D的输出.两者都坚持按值传递32字节结构有问题的函数是添加成员并返回值,没有修改传入的结构.C++版本如下.
#include "iostream.h"
struct S {
int i, j, k, l, m, n, o, p;
};
int foo(S s) {
return s.i + s.j + s.k + s.l + s.m + s.n + s.o + s.p;
}
int main() {
S s;
int bar = foo(s);
cout << bar;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么这样的东西不会被编译器优化为传递引用而不是实际将所有这些推int送到堆栈上?
注意:使用的编译器开关:GCC -O2(-O3内联foo().),DMD -O -inline -release.
编辑:显然,在一般情况下,传值和传递引用的语义将不相同,例如,如果涉及复制构造函数或在被调用者中修改原始结构.但是,在许多现实场景中,语义在可观察行为方面是相同的.这些是我要问的案例.
compiler-construction optimization performance assembly struct
考虑以下代码:
struct s { /* ... */ };
void f(struct s x) { /* ... */) /* (1) */
/* or */
void f(const struct s *x) { /* ... */ } /* (2) */
Run Code Online (Sandbox Code Playgroud)
什么时候struct s有合适的尺寸,在这种情况下我们应该更喜欢第一种形式?
我最近写了很多程序来struct绕过函数,以避免全局变量.但是,我想知道传递struct自身或其指针是否更有效.它听起来应该是这样,因为指针(在我的64位GNU/Linux系统上)是8个字节,而struct充满指针显然远不止于此.
但是,如果我有这个struct:
struct Point {
int x;
int y;
}
Run Code Online (Sandbox Code Playgroud)
这是8个字节,与指针大小相同,是将整个struct传递给函数还是传递指针更好?我非常精通C内存分配,因此malloc在初始化指针时使用和朋友不是问题.
另一个想法是,如果它们很大,直接传递结构会占用大量的堆栈空间.然而,简单地使用指针会耗尽内存,这free很容易编辑.
当您为内存分配空间时,如何判断是否需要为其分配更多空间?是否有检查或您可以对新内存进行检查以确保它运行正常?(为结构分配内存)。
因为我在想的是,结构是一组数据,即使我传递了很多数据,它也永远不需要超过结构正确的大小?
c ×5
struct ×4
performance ×2
pointers ×2
assembly ×1
coding-style ×1
linux ×1
memory ×1
optimization ×1
shallow-copy ×1