假设“structName”是定义的结构:这段代码真的在做什么?
structName ** sarray = (structName **) malloc(0 * sizeof(structName *));
我知道它创建一个指向名为sarray一个结构指针,但为什么会有放置在表达式的开始(structName **)?另外,为什么malloc调用中的struct size乘以0?
代码的源是here
假设“structName”是定义的结构:这段代码真的在做什么?
structName ** sarray = (structName **) malloc(0 * sizeof(structName *));
我知道它创建一个指向名为sarray一个结构指针,但为什么会有放置在表达式的开始(structName **)?另外,为什么malloc调用中的struct size乘以0?
代码的源是here
malloc
返回void *
。指针sarray
的类型为structName **
。 (structName **)
是一种类型转换,将void *
转换为structName **
。指针在C中非常可塑; malloc
将始终返回可以安全地投射到任何种类的指针的东西。在这种情况下,您有一个指向structName *
的指针。
乘以sizeof(structName *)
由0
做你的想法,要求malloc
一个零长度的内存块。我怀疑sizeof
在那里,因为作者认为它是标准模式。你可以删除它,没有任何后果,只是提供0.鉴于realloc
与NULL
参数一起使用,你也可以只是初始化sarray
到NULL
。
对于记录,为malloc
:
如果所请求的空间的大小是零,则该行为定义 implementation-:返回任一个空指针,或 行为是因为如果大小是非零值,但不应使用返回的指针访问对象。
因此,初始调用可能返回或不返回NULL
,结果基本相同:通过指针访问任何内容应该有未定义的结果。
谢谢。我现在明白了。 – AJPennster 2014-10-07 00:29:27
malloc函数返回类型为(void *)的指针。 (structName **)将该指针转换为类型(structName **)。这种转换在C. 中不是必需的,他乘以0,因为他不想分配任何结构,并且稍后等待重新分配。
为什么
(structName **)
放置在表达式的开头?
它被称为type casting。 malloc
returns a void *
这是铸造到structName **
,以便它可以被分配到sarray
。
此外,malloc调用中为什么struct size乘以0?
编码模式malloc(size * sizeof(datatype))
通常随处可见,因此在那里使用乘法IMO。
structName ** sarray = (structName **) malloc(0 * sizeof(structName *));
等同于:
structName ** sarray = NULL;
的原因(structName **)
是的malloc()
返回值从void *
转换为(structName **)
,所以分配给sarray
不会产生不兼容的类型错误。
原因被零乘法与下面的语句兼容性:
long sarray_len = 0;
如果例如选择了先从
long sarray_len = initialCount;
代替,那么malloc
必须是
structName ** sarray = (structName **) malloc(initialCount * sizeof(structName *));
。
(structName **)
之前malloc
是一个错误。它是在20世纪70年代需要的,但自1989年以来一直是一个错误。许多人没有更新自1989年以来的学习材料;-)
充其量是多余的文本(通常应避免多余的文本,因为它使难以阅读的重要文本),最糟糕的是它可以隐藏一个错误。有关该主题的进一步阅读see this thread。
关于第二部分,0 * sizeof(structName *)
。这当然是0
,你可能会问为什么这个人不写0
。
原因是该人符合使用malloc的特定风格。符合模式是最小化错误的一种方式。如果您经常阅读本网站,您将会知道,错误地使用malloc是人们无法追查的最常见错误之一。所使用的模式为:
T *ptr = (T *) malloc(number_of_elements * sizeof(T));
其中分配一定数目的T
类型的元素的阵列。即使数字为0
(但对于负数不合法),这也是合法的。在这种情况下,它可以返回一个空指针或一个非空指针。无论哪种情况,当然你都不能尝试访问任何数组元素。
这种模式很常见,但正如链接线程中提到的那样,存在问题,并且自1989年以来存在更好的选择。
注意:考虑使用calloc
分配内存。由于两个数字之间用逗号分隔,而不是乘法运算符,所以稍微清晰一些,在某些操作系统(例如Linux)上,它的执行速度可能快于malloc
。
我的猜测是'0'是一个硬编码的幻数,而你的前任曾经把它作为一个非零值。 '(structName **)'是一个类型转换。编辑:它看起来像数组应该增长使用'realloc',但开始为'0'大小。 'sizeof(structName *)'可能只是包含在内,因为它的良好实践。 – acbabis 2014-10-06 23:32:07
代码开始为将根据需要展开的数组分配一个零大小的块(或试图分配一个块)。这是有效的,但是任何做这种事情的人都需要小心 - malloc()被指定为可以将NULL或地址返回到零大小的内存块。在示例代码的情况下,这是可以的,因为在扩展零大小的块或NULL指针时,realloc()将表现良好。 – 2014-10-06 23:34:50
问:这行代码真的在做什么?简答:没有用。较长的回答:1)我推迟'malloc()',直到我有一个非零值分配,2)我一般喜欢形式'malloc(sizeof结构名);',而不是指针指针**)。 – FoggyDay 2014-10-06 23:42:15