所有
我正在编写一个非常简单的动态二维数组声明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
时它不起作用。如果有人可以帮助我,那将是非常有帮助的。谢谢。
答案 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不保证在内存中是连续的,但这是你的代码所假设的。