结构体ExampleStruct的大小是多少或者*VarExampleStruct的大小是多少 - 哪种编码实践更好?

4

在向malloc调用中提及结构的大小时,是更好地提及结构的名称还是解引用结构指针变量?

例如:

struct ExampleStruct
{
  int x;
  char arr[40];
};

int main()
{

  struct ExampleStruct *Y = NULL;

  Y = malloc(sizeof(struct ExampleStruct)); //Is this better?

  Y = malloc(sizeof(*Y)); //Is this better?  

}

我个人更喜欢使用 sizeof(struct ExampleStruct),因为我见过许多开发者在第二种方法中漏掉 '*' 的错误,即他们错误地将其键入为 malloc(sizeof(Y)),在这种情况下,分配的内存仅为4个字节。但是,我也看到它被普遍使用。


1
仅供记录,发表了许多评论的用户Jay与提出问题的用户Jay不同。 - Jonathan Leffler
@Jonathan Leffer,感谢您的澄清。我是发布问题的人,而不是评论和回答的人。:) - Jay
那怎么会发生?通常来说,已经存在的用户名应该被系统阻止。 - glglgl
@Jay(这里有很多评论的那个人):只是一个“请求”,请缓和一下你有些激进的评论。我只是想发起一次健康的讨论并获得意见,以便我可以为我的团队提供一些编码指南。谢谢。 - Jay
@glglgl,我也很惊讶 - Jay(发布问题的人):( - Jay
显示剩余2条评论
4个回答

5

我肯定更喜欢第二个。如果声明的类型Y发生变化,这行代码仍然能够正确地工作。


4

我在K&R第二版中找到了三个有关使用malloc()的相关例子:

  • 第142页:return (struct tnode *) malloc(sizeof(struct tnode));

  • 第145页:np = (struct nlist *) malloc(sizeof(*np));

  • 第146页:return (Treeptr) malloc(sizeof(Treenode));

没有特别讨论不同形式。前言中有一句话:“我们广泛使用Bjarne Stroustrup的C++翻译器来测试我们的程序”。这是在1989 C标准最终确定之前写的(我的副本上面写着“基于草案提议的ANSI C”,所以那时还没有标准编译器),这可能解释了每个malloc()调用上都需要显式转换的原因-这在C ++中是必要的。

因此,“创始人”使用了两种形式。

现代风格是使用sizeof(*variable)符号(在C中省略转换),以便即使变量类型发生更改,您也不必更改此代码。添加转换,这个好处就消失了。

我的大部分旧代码倾向于使用sizeof(type)符号,部分原因是为了模拟K&R C中的样式。 我的大部分新代码现在都使用sizeof(*variable)符号。 当我期望将代码编译为C ++和C时,我也会添加转换。


1
在K&R中,malloc的转换来自于需要转换的pre-ANSI时期。在K&R2nd勘误表中有一个有趣的提到(由于SO而被截断):“关于强制转换malloc的返回值的评论[...]需要重新编写。示例是正确的并且有效,但是建议在1988-1989 ANSI / ISO标准的背景下是有争议的。如果malloc或其代理未声明为返回void *,则没有必要[...],并且可能会有害。显式转换可以掩盖意外错误。另一方面,在pre-ANSI中,强制转换是必要的[...]” - ouah

1
通常第二个参数的论点是,当Y的类型改变时,malloc()仍然可以工作。但是,通常在语句后面有初始化代码,用于初始化旧类型的Y。如果它仍然适用于新类型,则必须至少对其进行审查。更多的计划涉及到类型更改才能“正常工作”。
此外,第二个参数通常需要编写较少的代码,并且以后需要阅读的代码也较少。
我更喜欢更进一步地使用创建和销毁函数来处理这种情况。创建函数不返回void指针,而是正确的类型。因此,如果Y的类型发生更改,但我没有更改调用(并审查以下初始化代码),则编译器会给我一个错误。
此外,这使得资源管理比在代码中随意抛出malloc()free()调用要容易得多。

1

我更喜欢:

Y = malloc(sizeof(struct ExampleStruct));

因为这是数据类型,你可以将其用于其他目的。 例如:

Y = malloc(sizeof(struct ExampleStruct) * 5);

例子:

int *i;

我更喜欢:

i = malloc(sizeof(int));

比起,

i = malloc(sizeof(*i);

另外,提醒一下,这个变量 i 是一个指向 int 的指针,而 Y 是一个指向 struct ExampleStruct 的指针。


1
你同样可以轻松地编写 malloc(sizeof(*Y) * 5),它也能正常工作。 - Jonathan Leffler
是的,这是真的。但我更喜欢使用数据类型。此外,如果已经使用了typedef,那就更好了。 - Oki Sallata
@Jonathan,请看我的下面评论...我不同意。 - Jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接