简体   繁体   English

C约定 - 如何在struct的数组字段上使用memset

[英]C conventions - how to use memset on array field of a struct

I wold like to settle an argument about proper usage of memset when zeroing an array field in a struct (language is C). 在将结构中的数组字段归零(语言为C)时,我想解决关于正确使用memset的争论。

Let say that we have the following struct: 假设我们有以下结构:

  struct my_struct {
        int a[10]
    }

Which of the following implementations are more correct ? 以下哪个实现更正确?

Option 1: 选项1:

void f (struct my_struct * ptr) {
    memset(&ptr->a, 0, sizeof(p->a));
}

Option 2: 选项2:

void f (struct my_struct * ptr) {
        memset(ptr->a, 0, sizeof(p->a));
}

Notes: 笔记:

If the field was of a primitive type or another struct (such as 'int') option 2 would not work, and if it was a pointer (int *) option 1 would not work. 如果字段是基本类型或另一个结构 (例如'int'),则选项2将不起作用,如果它是指针(int *),则选项1将不起作用。

Please advise, 请指教,

For a non-compound type, you would not use memset at all, because direct assignment would be easier and potentially faster. 对于非复合类型,您根本不会使用memset ,因为直接赋值会更容易且可能更快。 It would also allow for compiler optimizations a function call does not. 它还允许函数调用不进行编译器优化。

For arrays, variant 2 works, because an array is implictily converted to a pointer for most operations. 对于数组,变体2可以工作,因为对于大多数操作,数组被有意地转换为指针。

For pointers, note that in variant 2 the value of the pointer is used, not the pointer itself, while for an array, a pointer to the array is used. 为指针,请注意,在变体2中的指针的时,不指针本身,而对于一个阵列中,使用一个指针数组

Variant 1 yields the address of the object itself. 变体1产生对象本身的地址。 For a pointer, that is that of the pointer (if this "works" depends on your intention), for an array, it is that of the array - which happens to always be the address of its first element - but the type differs here (irrelevant, as memset takes void * and internally converts to char * ). 对于指针,即指针的指针(如果这“工作”取决于你的意图),对于数组,它是数组的指针 - 它恰好总是第一个元素的地址 - 但这里的类型不同(无关紧要,因为memset采用void *并在内部转换为char * )。

So: it depends; 所以:这取决于; for an array, I do not see much difference actually, except the address-operator might confuse reads not so familar with operator preceedence (and it is more to type). 对于一个数组,我实际上没有看到太大的区别,除了地址运算符可能会混淆不那么熟悉的运算符优先级(并且更多的是键入)。 As a personal opinion: I prefer the simpler syntax, but would not complain about the other. 作为个人意见:我更喜欢更简单的语法,但不会抱怨另一个。

Note that memset with any other value than 0 does not make much sense actually; 请注意,任何其他值不超过0 memset实际上没有多大意义; it might not even guarantee an array of pointers to be interpreted as null pointer . 它甚至可能不能保证一个指针数组被解释为空指针

IMO, option 1 is preferable because the same pattern works for any object, not just arrays: IMO,选项1是首选,因为相同的模式适用于任何对象,而不仅仅是数组:

memset(&obj, 0, sizeof obj);

You can tell just from this statement that it does not cause a buffer overflow -- ie does not access out of bounds. 你可以从这个语句中断言它不会导致缓冲区溢出 - 即不会访问越界。 It's still possible that this doesn't do what was intended (eg if obj is a pointer and it was intended to set what the pointer was pointing to), but at least the damage is contained. 它仍然可能不会达到预期的效果(例如,如果obj是一个指针,它的目的是设置指针指向的内容),但至少包含了损坏。

However if you accidentally use memset(p, 0, sizeof p) on a pointer then you may write past the end of the object being pointed to; 但是,如果您不小心在指针上使用memset(p, 0, sizeof p) ,那么您可以写入指向的对象的末尾; or if the object is bigger than sizeof p , you leave the object in a weird state. 或者如果对象大于sizeof p ,则将对象置于奇怪的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM