具有单个成员的struct
与成员类型(内存使用和速度)具有相同的性能吗?
示例:
此代码是struct
,只有一个成员:
struct my_int
{
int value;
};
my_int
的效果是否与int
相同?
答案 0 :(得分:5)
总体上同意@harper,但请注意以下事项:
在“非结构化”数组和结构中的数组中可以看到经典差异。
char s1[1000];
// vs
typedef struct {
char s2[1000];
} s_T;
s_T s3;
调用函数时......
void f1(char s[1000]);
void f2(s_T s);
void f3(s_T *s);
// Significant performance difference is not expected.
// In both, only an address is passed.
f1(s1);
f1(s3.s2);
// Significant performance difference is expected.
// In the second case, a copy of the entire structure is passed.
// This style of parameter passing is usually frowned upon.
f1(s1);
f2(s3);
// Significant performance difference is not expected.
// In both, only an address is passed.
f1(s1);
f3(&s3);
答案 1 :(得分:3)
如果编译器对使用结构而不是单个变量有任何惩罚,则严格依赖于编译器和编译器选项。
但是,当结构只包含一个成员时,编译器没有任何理由可以产生任何差异。应该有额外的代码来访问成员,也不需要解除任何指向这种结构的指针。如果您没有这种过度简化的结构,一个成员引用可能会花费一个额外的CPU指令,具体取决于所使用的CPU。
答案 2 :(得分:1)
在某些情况下,ABI可能具有返回结构并将其传递给函数的特定规则。例如,给定
struct S { int m; };
struct S f(int a, struct S b);
int g(int a, S b);
例如,调用f
或g
可以在寄存器中传递a
,并在堆栈上传递b
。同样,调用g
可能会使用寄存器作为返回值,而调用f
可能需要调用者设置f
将存储其结果的位置。
这种性能差异通常应该可以忽略不计,但是一个可以产生显着差异的情况是这种差异启用或禁用尾递归。
假设g
已实施为int g(int a, struct S b) { return g(a, b).m; }
。现在,在f
的结果以与g
相同的方式返回的实现中,这可以编译为(来自clang的实际输出)
.file "test.c" .text .globl g .align 16, 0x90 .type g,@function g: # @g .cfi_startproc # BB#0: jmp f # TAILCALL .Ltmp0: .size g, .Ltmp0-g .cfi_endproc .section ".note.GNU-stack","",@progbits
但是,在其他实现中,这样的尾调用是不可能的,所以如果你想为深度递归函数获得相同的结果,你真的需要给f
和g
相同的返回类型或您冒着堆栈溢出的风险。 (我知道尾部调用不是强制性的。)
此不意味着int
比S
更快,也不意味着S
比int
更快。无论是使用int
还是S
,内存使用都是相似的,只要始终使用相同的内存即可。
答案 3 :(得分:0)
一个带有 GCC 10.2.0 -O3 的最小示例给出完全相同的输出,即没有结构引入的开销:
diff -u0 <(
gcc -S -o /dev/stdout -x c -std=gnu17 -O3 -Wall -Wextra - <<EOF
// Out of the box
void OOTB(int *n){
*n+=999;
}
EOF
) <(
gcc -S -o /dev/stdout -x c -std=gnu17 -O3 -Wall -Wextra - <<EOF
// One member struct
typedef struct { int inq_n; } inq;
void OMST(inq *n){
n->inq_n+=999;
}
EOF
)
--- /dev/fd/63 [...]
+++ /dev/fd/62 [...]
@@ -4,3 +4,3 @@
- .globl OOTB
- .type OOTB, @function
-OOTB:
+ .globl OMST
+ .type OMST, @function
+OMST:
@@ -13 +13 @@
- .size OOTB, .-OOTB
+ .size OMST, .-OMST
不确定更现实/更复杂的情况。