C 在结构中保存变量

C 在结构中保存变量,c,struct,C,Struct,我的代码中有一个高性能的关键部分,我需要尽可能减少cpu负载。如果我的结构只有一个实例,那么像这样在代码中定义变量在性能上有什么不同吗 int something; int randomVariable; 或者在struct中定义它们 struct Test { int something; int randomVariable; } 因为我想用struct让代码看起来更好,公平地说,因为我想用struct让代码看起来更好纯粹是一种风格。在一个人看来更好的东西

我的代码中有一个高性能的关键部分,我需要尽可能减少cpu负载。如果我的结构只有一个实例,那么像这样在代码中定义变量在性能上有什么不同吗

    int something;
    int randomVariable;
或者在struct中定义它们

struct Test
{
    int something;
    int randomVariable;
}
因为我想用struct让代码看起来更好,公平地说,因为我想用struct让代码看起来更好纯粹是一种风格。在一个人看来更好的东西在另一个人看来未必更好

当有选择的时候,出于几个原因,我是
struct
的粉丝

速度/尺寸效率:
当数据需要作为函数参数传递时,在两个离散的
int
变量上比较
struct

使用:

int a;
int b;

相同的数据可以通过函数参数作为单独的指针传递(假设32位寻址):

或:

(这种类型的)效率随着变量数量的增加而直接提高。
(如果有100整数,效率提高?)

在第一个示例中,传递两个
int*
,而在第二个示例中,只传递一个。这是一个小差别,但它是一个差别。优势的大小也取决于所使用的寻址。32位或64位

代码维护和可读性:
当用作应用程序编程接口()时,函数原型应该是稳定的。使用
struct
作为参数或返回类型支持这种接口稳定性

例如:如果需要计算沿直线移动的对象相对于时间的x、y和z的变化速度,则可以设计一个函数,该函数将使用当前值velocityxyz和accelerationxyz以及timems重复调用。所需的参数数量清楚地表明使用了
struct
。还建议将Struct作为返回类型:

typedef struct {
    double x;
    double y;
    double z;
}VEL; //velocity

typedef struct {
    double x;
    double y;
    double z;
}ACC; //acceleration

typedef struct {
    VEL vel;
    ACC acc;
    time_t ms;
}KIN; //kinematics

KIN * GetVelocity(KIN *newV);
如果向项目中添加了了解位置XYZ的新要求,则需要添加的只是KIN结构的新成员:

typedef struct {
    double x;
    double y;
    double z;
}POS; //position
...
typedef struct {
    POS pos;
    VEL vel;
    ACC acc;
    time_t ms;
}KIN; //kinematics

KIN * GetVelocity(KIN *newV);//prototype will continue to work 
                             //without changing interface (argument list)
KIN * GetPosition(KIN *newV);//new prototype for position also supported

在我看来,了解这一点的最好方法是,首先用C编写两个不同的程序,使用struct和不使用struct,然后使用

gcc-S file.c

因为我不知道你的代码,我直接给它们赋值:

int main() {
     int something;
     int randomVariable;
     something = 3;
     randomVariable = 3;
    return 0;}

我在我的Ubuntu-64位英特尔i5机器上获得汇编文件

我看到汇编文件几乎是一样的

.file   "test1.c"
.text
.globl  main
.type   main, @function
main:
.LFB0:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
movl    $3, -8(%rbp) **Second one(with struct) has value -16 instead -8**
movl    $3, -4(%rbp) **Second one has value -12 instead of -4**
movl    $0, %eax
popq    %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size   main, .-main
.ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section    .note.GNU-stack,"",@progbits

所以根据这个结果,我可以说这两个实现在CPU负载方面并没有任何显著的差异。它们之间唯一的区别是,第二个使用的内存比第一个少很多

使用2
int
可以防止发生任何类型转换,但许多编译器无论如何都会对此结果进行优化。这取决于上下文。您希望优化的代码[片段]是什么?如果您对性能感兴趣,我假设您已经反汇编了编译器输出,并构建了能够以[纳秒]分辨率对代码进行基准测试的基础设施——是吗?速度、大小、代码维护、可读性?你能更详细地说明一下你的意思吗:最小化cpu负载1)库的接口保持不变是可取的。如果您保持相同的原型,但实际上采用完全不同的
结构
,并使用您获得的新信息执行不同的操作,那么您的界面根本就没有保持不变,您已经完全改变了它。2) 在我的原始帖子(已编辑,但您可以查看编辑内容)中,将一组断开连接的变量包装在一个
结构中,以便将它们传递给一组不相关的函数,其中大多数函数不会使用大多数变量,这是我听过的最糟糕的想法之一。@PaulGriffiths-关于1)我主张保持论点列表不变。我没有说过使用完全不同的结构。我解释了如何在不破坏函数原型的情况下使用修改后的结构(通过添加成员)。关于2),我从来没有说过不相关或断开连接,但我同意,我在原始答案中使用的变量列表和函数原型示例并不表明任何目的的连续性。我已经编辑了答案。
typedef struct {
    double x;
    double y;
    double z;
}POS; //position
...
typedef struct {
    POS pos;
    VEL vel;
    ACC acc;
    time_t ms;
}KIN; //kinematics

KIN * GetVelocity(KIN *newV);//prototype will continue to work 
                             //without changing interface (argument list)
KIN * GetPosition(KIN *newV);//new prototype for position also supported
int main() {
     int something;
     int randomVariable;
     something = 3;
     randomVariable = 3;
    return 0;}
main() {
struct Test
{
    int something;
    int randomVariable;
}test;
test.something = 3;
test.randomVariable = 3;
return 0;}
.file   "test1.c"
.text
.globl  main
.type   main, @function
main:
.LFB0:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
movl    $3, -8(%rbp) **Second one(with struct) has value -16 instead -8**
movl    $3, -4(%rbp) **Second one has value -12 instead of -4**
movl    $0, %eax
popq    %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size   main, .-main
.ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section    .note.GNU-stack,"",@progbits