0

全部

我正在编写一个非常简单的动态二维数组声明的 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. 如果有人可以帮助我,那将非常有帮助。谢谢你。

4

3 回答 3

3

Firstly, the usual advice: stop using type names under sizeof and stop casting the result of malloc. This is what it should've looked like

env = malloc(num * sizeof *env);

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

In general, prefer to write you memory allocations by following this pattern

some_ptr = malloc(N * sizeof *some_ptr);

Secondly, the "array" you create by using this technique is not a classic C-style contiguous 2D array. Instead, you get a "simulated" 2D array assembled from a bunch of completely unrelated 1D arrays. The latter can potentially be scattered randomly in memory. This immediately means that you won't be able to process your array as a continuous object. Meanwhile your memset call attempts to do just that. You can't do it this way. In your case you have to zero each 1D sub-array independently, using a cycle.

However, instead of allocating your 1D sub-arrays independently, you can allocate them all as a single memory block

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;

If allocated as shown above, you array's data will be stored in a single continuous memory block, although you still have to understand what you are doing when you are working with that array. For example, memseting the array data would look as follows

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

or

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

(which is the same thing).

于 2012-11-03T19:07:24.167 回答
2

Remove the memset and use calloc instead of malloc, it zero-initializes allocated memory. What you're doing now is zeroing pointers you have just allocated.

于 2012-11-03T18:55:42.417 回答
2

In addition to Michael's answer, it is important to realize that float **env will not give you a continuous chunk of memory. It will give you a pointer to a continuous chunk of memory, and in each of those memory locations is a pointer to a continuous chunk of memory, but there is no guarantee that those chunks are aligned.

For example doing:

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

x and y are not guaranteed to be continuous in memory, yet this is what your code is assuming.

于 2012-11-03T19:01:06.753 回答