取消引用未初始化的指针以传递给 sizeof()
Dereferencing an uninitialized pointer to pass into sizeof()
在最近的 post 中,我意识到在分配结构变量时,传递取消引用的指针被认为是比将结构类型传递给 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
仍然是 unconstructed/uninitialized 内存,这表明在 sizeof()
内发生的 obj1
取消引用不应该有效。
让我猜猜是什么让方法 1 有效。这是因为 sizeof()
是一个编译时操作,取消引用 obj1
被编译器翻译成 方法 2?
请问有哪位能参考相关的C标准详细说明一下技术有效性吗?
操作数不是可变长度数组的 sizeof 表达式是非计算表达式。所以这个表达式
sizeof(*obj1)
格式正确。
来自 C 标准(6.5.3.4 sizeof 和 alignof 运算符)
2 The sizeof operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is
determined from the type of the operand. The result is an integer.
If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the
result is an integer constant
关于你关于指定 malloc 参数的最佳方法的问题
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
X* obj2 = malloc(sizeof(X)); // ----> method 2
然后如果类型 X
在使用 malloc 时是可见的,就像在这种情况下
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
那么这种方法更可取。
但是,如果类型不可见,例如
obj1 = malloc(sizeof(*obj1)); // ----> method 1
然后我更喜欢明确指定类型
obj1 = malloc(sizeof( X ));
否则例如这个代码片段
p = malloc( *p );
q = malloc( *q );
没有为代码的 reader 提供足够的信息。 reader 需要前后滚动源代码才能找到 p
和 q
的声明以确定它们的类型。
The question is, how valid is it to dereference obj1
in method 1?
100% 有效。不过,您可以在不带括号的情况下使用它,sizeof *obj1
.
来自N1570 ISO/IEC 9899:201x §6.5.3.4 The sizeof and _Alignof operators
2 -
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
事实上,可以说这是一种更可取的方法,原因是如果您出于某种原因更改了对象的类型,很容易忘记使用解除引用的方式也更改 sizeof
参数指针将避免这种潜在的无提示错误。
在最近的 post 中,我意识到在分配结构变量时,传递取消引用的指针被认为是比将结构类型传递给 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
仍然是 unconstructed/uninitialized 内存,这表明在 sizeof()
内发生的 obj1
取消引用不应该有效。
让我猜猜是什么让方法 1 有效。这是因为 sizeof()
是一个编译时操作,取消引用 obj1
被编译器翻译成 方法 2?
请问有哪位能参考相关的C标准详细说明一下技术有效性吗?
操作数不是可变长度数组的 sizeof 表达式是非计算表达式。所以这个表达式
sizeof(*obj1)
格式正确。
来自 C 标准(6.5.3.4 sizeof 和 alignof 运算符)
2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant
关于你关于指定 malloc 参数的最佳方法的问题
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
X* obj2 = malloc(sizeof(X)); // ----> method 2
然后如果类型 X
在使用 malloc 时是可见的,就像在这种情况下
X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
那么这种方法更可取。
但是,如果类型不可见,例如
obj1 = malloc(sizeof(*obj1)); // ----> method 1
然后我更喜欢明确指定类型
obj1 = malloc(sizeof( X ));
否则例如这个代码片段
p = malloc( *p );
q = malloc( *q );
没有为代码的 reader 提供足够的信息。 reader 需要前后滚动源代码才能找到 p
和 q
的声明以确定它们的类型。
The question is, how valid is it to dereference
obj1
in method 1?
100% 有效。不过,您可以在不带括号的情况下使用它,sizeof *obj1
.
来自N1570 ISO/IEC 9899:201x §6.5.3.4 The sizeof and _Alignof operators
2 - The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer.
If the type of the operand is a variable length array type, the operand is evaluated;otherwise, the operand is not evaluated and the result is an integer constant.
事实上,可以说这是一种更可取的方法,原因是如果您出于某种原因更改了对象的类型,很容易忘记使用解除引用的方式也更改 sizeof
参数指针将避免这种潜在的无提示错误。