假设n
是一个整数(C中的int
变量),我需要足够的空间来容纳"4倍n的上限除以3"字节。我怎么保证有足够的空间放这个?
你认为malloc(4*(int)ceil(n/3.0))
会做,或者我必须添加,说,1
为了绝对安全(由于可能的舍入误差)?
你可以用纯整数运算来实现同样的事情,这保证了你分配了正确的内存量:edit固定括号
malloc(4*((n+2)/3))
KerrekSB的一般公式保证只使用一次除法,另一种替代方法是计算
(n + m - 1)/m
要看到它产生相同的结果,将n = k*m + r
写入0 <= r < m
。然后是n%m == r
,如果是r == 0
,我们有n+m-1 = k*m + (m-1)
和(n+m-1)/m == k
,否则是n+m-1 = (k+1)*m + (r-1)
和(n+m-1)/m == k+1
。
大多数现代硬件在一个寄存器中提供商(n/m
),在另一个寄存器中提供余数(n%m)
,当您进行整数除法时,因此您可以在一次除法中获得Kerrek公式的两个部分,并且大多数编译器都会这样做。如果编译器不这样做,而是使用两个除法,计算将会相当慢,所以如果经常进行计算并且性能是一个问题,您可以使用稍微不那么明显的代码来解决编译器的弱点。
在给定的情况下,malloc
将是
malloc(4*((n+2)/3));
但由于不是每个人都清楚这个公式的作用,如果你使用它,在注释中解释它,如果你不需要使用它,使用更明显的代码
要完整计算n / m
的上限,只需输入:
n / m + (n % m == 0 ? 0 : 1)
总而言之,说是malloc(4 * (n / 3 + (n % 3 ? 1 : 0)));
虽然Kerrek SB有一个精确的答案,但在实践中,大多数工程师会使用malloc (4 + 4 * n / 3)
或(等效的)malloc (4 * (1 + n / 3))
。C
的规则将n/3
计算为整数,导致截断剩余部分。在表达式中再添加一点,可确保分配被除法忽略的任何分数。
最多可能浪费三个字节。只有当有成千上万个这样的节点时,任何额外的计算才有可能被证明是合理的。malloc
的实现通常将存储分配四舍为4、8或16字节的倍数,以简化其管理。
考虑3字节内存的成本:当前的定价是每gb 5到15美元。