浮点数组上的memset不会完全清零数组

时间:2016-05-31 21:06:32

标签: c arrays dynamic

我有一些数组,

float *large_float_array;

我是calloc并在循环后尝试memset

large_float_array = (float*)calloc(NUM, sizeof(float));

// .. do stuff with float array

memset(large_float_array, 0, sizeof(large_float_array);

// .. do other stuff

但似乎large_float_array实际上并未归零。为什么是这样?这是由于浮点数的特殊属性吗?如果是这样,我想知道如何解决这个问题。

P.S。 calloc实际上也在这里工作吗?

4 个答案:

答案 0 :(得分:5)

你不能使用memset,因为它接受int作为值类型,但float可能以不同的方式存储,所以你应该使用常规循环

size_t i
for(i = 0; i < NUM; ++i){
    large_float_array[i] = 0.;
}

答案 1 :(得分:3)

calloc初始化内存区域并使用memset函数实现0值的效果实际上是相同的。换句话说,calloc不再是memset的“类型”。它们都只是将所有位设置为内存*。

C11(N1570)7.22.3.2/2 calloc函数

  

calloc函数为nmemb对象数组分配空间,   每个尺寸都是大小。空间初始化为所有位零。 296)

脚注296(仅供参考):

  

请注意,这不一定与表示相同   浮点零或空指针常量。

*)可以想象calloc可以返回已经使用零预先初始化的内存位置的地址,因此它可能比malloc + memset组合更快。

答案 2 :(得分:3)

由于large_float_array是指针,因此不能使用sizeof(large_float_array)指定要清除的字节数。你必须写:

memset(large_float_array, 0, NUM * sizeof(float));

请注意,C标准并未严格指定将所有位设置为零,因为将所有值设置为0.0。但在大多数当前架构中,它将按预期工作。

清除阵列的正确方法是:

#include <stdlib.h>

...
for (size_t i = 0; i < NUM; i++) {
    large_float_array[i] = 0;
}

答案 3 :(得分:1)

发布有多个问题。

以下没有均衡()。不清楚OP的真实代码是什么。

memset(large_float_array, 0, sizeof(large_float_array);

假设上面的简单使用了另一个),那么代码只用零填充几个字节为零,因为sizeof(large_float_array)是指针的大小。

memset(large_float_array, 0, sizeof(large_float_array));

OP可能想要一些零填充已分配空间的零位。这将使分配的内存处于与calloc()相同的状态。

memset(large_float_array, 0, NUM *sizeof *large_float_array);

代码应该使用以下内容。一个好的编译器会将这个简单的循环优化为快速代码。

for (size_t i=0; i<NUM; i++) {
  large_float_array[i] = 0.0f;
}

使用快速memcpy()的一种方法是将float复制到数组的第一个元素,然后将第一个元素复制到第二个元素,然后将前两个元素复制到元素3&amp; 4,然后前4个元素到元素4,5,6,7 ...

void *memset_size(void *dest, size_t n, const char *src, size_t element) {
  if (n > 0 && element > 0) {
    memcpy(dest, src, element);  // Copy first element
    n *= element;
    while (n > element) {
      size_t remaining = n - element;
      size_t n_this_time = remaining > element ? element : remaining;
      memcpy((char*)dest + element, dest, n_this_time);
      element += n_this_time;
    }
  }
  return dest;
}

float pi = M_PI;
float a[10000];
memset_size(a, 10000, &pi, sizeof pi);

与所有优化一样,首先考虑清楚编写的代码,然后在有选择的案例中使用上述候选人。