具有单个成员的struct是否具有与成员类型相同的性能?

时间:2013-11-09 15:44:08

标签: c performance struct member

具有单个成员的struct与成员类型(内存使用和速度)具有相同的性能吗?

示例

此代码是struct,只有一个成员:

struct my_int
{
    int value;
};

my_int的效果是否与int相同?

4 个答案:

答案 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);
例如,

调用fg可以在寄存器中传递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

但是,在其他实现中,这样的尾调用是不可能的,所以如果你想为深度递归函数获得相同的结果,你真的需要给fg相同的返回类型或您冒着堆栈溢出的风险。 (我知道尾部调用不是强制性的。)

意味着intS更快,也不意味着Sint更快。无论是使用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

不确定更现实/更复杂的情况。