不寻常的初始化问题

时间:2012-11-03 18:50:44

标签: c multidimensional-array initialization

所有

我正在编写一个非常简单的动态二维数组声明C代码,并用memset初始化它,然后打印出该值。我的代码如下:

float **env;
int i,j,num;

printf("Enter a number : \n");
scanf("%d",&num);

env = (float **)malloc(num*sizeof(float *));

for(i=0;i<num;i++)
{env[i] = (float *)malloc(num*sizeof(float));}

memset(env, 0, sizeof(float)*num*num);

for(i=0;i<num;i++)
{  for (j=0;j<num;j++)
   {
      printf("%f\t",env[i][j]);
      if (j == num -1)
       { printf("\n\n");}
    }
}

for(i=0;i<num;i++)
{free(env[i]);
}

free(env);

当我编译程序时,没有编译错误或警告,但当我尝试打印出值时,我无法打印它们。然后我调试了程序,在memset语句后,env 2D变量显示了类似的东西 CXX0030: Error: expression cannot be evaluated,当我打印值时会出现一个显示

的窗口

Unhandled exception at 0x008b1e27 in ***.exe: 0xC0000005: Access violation reading location 0x00000000.

我尝试使用2 for循环显式初始化2D数组env为0并且它完美地运行并且我也能够打印值,但是当我使用memset时它不起作用。如果有人可以帮助我,那将是非常有帮助的。谢谢。

3 个答案:

答案 0 :(得分:3)

首先,通常的建议是:停止在sizeof下使用类型名称并停止投射malloc的结果。这应该是它看起来像

env = malloc(num * sizeof *env);

for (i = 0; i < num; i++)
  env[i] = malloc(num * sizeof *env[i]);

通常,您更喜欢按照此模式编写内存分配

some_ptr = malloc(N * sizeof *some_ptr);

其次,使用此技术创建的“数组”不是经典的C风格连续2D数组。相反,您将从一堆完全不相关的1D阵列中获得“模拟”2D阵列。后者可能在内存中随机分散。这立即意味着您将无法将阵列作为连续对象进行处理。同时,您的memset电话会尝试这样做。你不能这样做。在您的情况下,您必须使用循环独立地将每个1D子阵列归零。

但是,您可以将它们全部分配为单个内存块,而不是单独分配1D子阵列

assert(num > 0);
env = malloc(num * sizeof *env);
env[0] = malloc(num * num * sizeof *env[0]);

for (i = 1; i < num; ++i)
  env[i] = env[i - 1] + num;

如果按上面所示进行分配,则数组的数据将存储在单个连续内存块中,尽管在使用该数组时仍需要了解正在执行的操作。例如,memset数组数据将如下所示

memset(*env, 0, num * num * sizeof **env);

memset(&env[0][0], 0, num * num * sizeof env[0][0]);

(这是同样的事情)。

答案 1 :(得分:2)

删除memset并使用calloc而不是malloc,它会对已分配的内存进行零初始化。你现在正在做的是归零你刚刚分配的指针。

答案 2 :(得分:2)

除了迈克尔的答案之外,重要的是要认识到float **env给你一连串的记忆。它将为您提供指向连续内存块的指针,并且在每个内存位置都是指向连续内存块的指针,但不能保证这些块是对齐的。

例如:

int *x = malloc(sizeof(int)); 
int *y = malloc(sizeof(int)); 

x和y不保证在内存中是连续的,但这是你的代码所假设的。