取消引用未初始化的指针以传递给 sizeof()

aep*_*aep 4 c malloc pointers sizeof language-lawyer

在最近的一篇文章中,我意识到在分配结构变量时,与将结构类型传递给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;
}
Run Code Online (Sandbox Code Playgroud)

问题是,obj1方法 1 中取消引用的有效性如何?Inside malloc,obj1仍然是未构造/未初始化的内存,这表明对obj1内部发生的解除引用sizeof()不应该是有效的。

让我猜猜是什么使方法 1有效。这是因为sizeof()编译器将取消引用的编译时操作obj1转换为方法 2吗?

有人可以参考相关的C标准详细说明这个的技术有效性吗?

Vla*_*cow 5

操作数不是可变长度数组的 sizeof 表达式是未计算的表达式。所以这个表情

sizeof(*obj1)
Run Code Online (Sandbox Code Playgroud)

格式良好。

来自 C 标准(6.5.3.4 sizeof 和 alignof 运算符)

2 sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或类型的括号名称。大小由操作数的类型决定。结果是一个整数。 如果操作数的类型是变长数组类型,则对操作数求值;否则,不计算操作数并且结果是整数常量

至于您关于指定 malloc 参数的最佳方法的问题

X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
X* obj2 = malloc(sizeof(X));     // ----> method 2
Run Code Online (Sandbox Code Playgroud)

那么如果X在这种情况下使用 malloc时该类型是可见的

X* obj1 = malloc(sizeof(*obj1)); // ----> method 1
Run Code Online (Sandbox Code Playgroud)

那么这种方法是可取的。

但是,如果类型不可见,例如

obj1 = malloc(sizeof(*obj1)); // ----> method 1
Run Code Online (Sandbox Code Playgroud)

然后我更喜欢明确指定类型

obj1 = malloc(sizeof( X ));
Run Code Online (Sandbox Code Playgroud)

否则,例如此代码片段

p = malloc( *p );
q = malloc( *q );
Run Code Online (Sandbox Code Playgroud)

没有为代码的读者提供足够的信息。并且读者需要向前和向后滚动源代码以找到它们的声明pq确定它们的类型。