为什么要使用struct的第一个元素的地址,而不是struct本身?

Mag*_*nus 59 c struct

我刚刚开始工作的另一个代码库,开发人员在复制/比较/设置时始终使用结构的第一个元素的地址,而不是结构本身.这是一个简单的例子.

首先是结构类型:

typedef struct {
    int a;
    int b;
} foo_t;
Run Code Online (Sandbox Code Playgroud)

然后有一个函数可以复制这样的结构:

void bar(foo_t *inp)
{
    foo_t l;
    ...
    memcpy(&l.a, &inp->a, sizeof(foo_t));
    ...
}
Run Code Online (Sandbox Code Playgroud)

我不会以memcpy这种方式写一个调用,我开始怀疑原始开发人员根本没有完全掌握C中的指针和结构.但是,现在我已经在两个不相关的代码库中看到了这个,没有普通开发人员所以我开始怀疑自己.

为什么要使用这种风格?

Art*_*tur 62

没人应该这样做.如果重新排列struct成员,则会遇到麻烦.


oua*_*uah 62

而不是:

memcpy(&l.a, &inp->a, sizeof(foo_t));
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

memcpy(&l, inp, sizeof(foo_t));
Run Code Online (Sandbox Code Playgroud)

虽然它可能是危险的并且具有误导性,但是这两个语句实际上在这里做同样的事情,因为C保证在第一个结构成员之前没有填充.

但最好的方法是使用简单的赋值运算符复制结构对象:

l = *inp;
Run Code Online (Sandbox Code Playgroud)

为什么要使用这种风格?

我的猜测:无知或严厉的纪律.

  • +1为最佳`l =*inp`.建议遥远的第二最好`memcpy(&l,inp,sizeof l)`. (9认同)
  • 无知?不太确定......我的意思是,他们*知道*(希望)两个东西是相同的并且由规范保证所以我认为你不能推断*缺乏该代码的知识,但只有一个*坏使用*这样的知识(如果经常更糟!). (2认同)

pli*_*nth 16

一个人不会.如果您曾a在结构中移动过或者在其之前插入了成员,那么您将引入一个内存粉碎错误.


Dar*_*one 12

此代码是不安全的,因为memcpy如果成员a不再是第一个成员,则重新排列结构的成员可能导致超出struct的边界访问.

但是,可以想象成员是在结构中有意排序的,程序员只想复制它们的一个子集,成员开始a并运行直到结构的结尾.如果是这种情况,则可以通过以下更改使代码安全:

    memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));
Run Code Online (Sandbox Code Playgroud)

现在结构成员可以重新排列成任何顺序,这memcpy将永远不会超出范围.