我刚刚开始工作的另一个代码库,开发人员在复制/比较/设置时始终使用结构的第一个元素的地址,而不是结构本身.这是一个简单的例子.
首先是结构类型:
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中的指针和结构.但是,现在我已经在两个不相关的代码库中看到了这个,没有普通开发人员所以我开始怀疑自己.
为什么要使用这种风格?
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)
为什么要使用这种风格?
我的猜测:无知或严厉的纪律.
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将永远不会超出范围.