在最近的一篇文章中,我意识到在分配结构变量时,与将结构类型传递给sizeof()
相比,传递去引用指针被认为是更好的做法。这主要是因为前者比后者对代码更改更有弹性。
这表明,在以下代码中,方法1被认为是比方式2更好的做法。
typedef struct X_ {
int x;
int y;
int z;
} X;
int main() {
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
X* obj2 = malloc(sizeof(X)); // ----> method 2
return 0;
}
问题是,在方法1中取消引用obj1
的有效性如何?在malloc
内部,obj1
仍然是未构造/未初始化的内存,这表明在sizeof()
内部发生的对obj1
的取消引用应该是无效的。
让我猜猜是什么使方法1有效。这是因为sizeof()
是一个编译时操作,所以编译器会将取消引用obj1
转换为方法2吗?
有人可以参考相关的C标准来详细说明这一点的技术有效性吗?
操作数不是可变长度数组的sizeof表达式是未求值的表达式。所以这个表达式
sizeof(*obj1)
成形良好。
来自C标准(6.5.3.4操作员的尺寸和排列(
2 sizeof运算符产生其操作数的大小(以字节为单位(可以是表达式或类型的带括号的名称。尺寸为根据操作数的类型确定。结果是一个整数。如果操作数的类型是可变长度数组类型,则计算操作数;否则,不计算操作数结果是一个整数常量
关于指定malloc 参数的最佳方法的问题
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
X* obj2 = malloc(sizeof(X)); // ----> method 2
那么如果类型X
在使用malloc-like的点上是可见的,在这种情况下是
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
那么这种方法是优选的。
但是,如果类型不可见,例如
obj1 = malloc(sizeof(*obj1)); // ----> method 1
那么我更喜欢明确地指定类型,比如
obj1 = malloc(sizeof( X ));
否则,例如这个代码片段
p = malloc( *p );
q = malloc( *q );
没有为代码的读者提供足够的信息。读者需要前后滚动源代码,以找到p
和q
的声明,从而确定它们的类型。
问题是,在方法1中取消引用
obj1
的有效性如何
它是100%有效的。不过,您可以使用不带括号的sizeof *obj1
。
来自N1570 ISO/IEC 9899:201x§6.5.3.4 操作员的尺寸
2-sizeof运算符产生其操作数的大小(以字节为单位(,该操作数可以是表达式或类型的带括号名称大小由操作数的类型决定。结果是一个整数
如果操作数的类型是可变长度数组类型,则计算操作数否则,不计算操作数,结果为整数常量
事实上,可以说这是一种更可取的方法,原因是如果出于某种原因更改对象的类型,很容易忘记更改sizeof
参数,使用取消围栏的指针将避免这种潜在的静默错误。