c / linux中二维数组的动态分配

时间:2011-06-05 16:22:10

标签: c memory dynamic multidimensional-array allocation

我无法弄清楚如何做malloc。以下代码只输入前5行然后停止,任何帮助将不胜感激!

// Read query points from query file------------------------------
double **queryPoint;

token=(char*)malloc(40);
int qp_count=0;

i=0;
qp_count=0;
while(fgets(line,sizeof(line),queryFile)!=NULL)
{
    queryPoint=(double*)malloc(sizeof(double**));
    queryPoint[qp_count]=(double*)malloc(sizeof(double*)*2);

    printf("line:%s",line); 

    token = strtok(line," ,\t");        

    queryPoint[qp_count][0]=atof(token);        
    token = strtok(NULL, " ,\t");

    printf("l[%d]=%lf \n",qp_count,queryPoint[qp_count][0]);

    queryPoint[qp_count][1]=atof(token);
    token = strtok(NULL, " ,\t");
    printf("l[%d]=%lf \n",qp_count,queryPoint[qp_count][1]);

    qp_count++;
}

{ 这是查询文件的形式

9.85797 5.72533
9.58711 2.09899
2.28203 7.19344
4.49096 5.50094
6.05297 1.60751
6.19901 1.52312

} ... 总计30行

8 个答案:

答案 0 :(得分:4)

queryPoint=(double*)malloc(sizeof(double**));
queryPoint[qp_count]=(double*)malloc(sizeof(double*)*2);

你显然已经对malloc的强制转换,大小和其他各种属性感到困惑,所以让我们从正确的malloc语法开始。

首先,在C中没有必要转换malloc操作的结果,因为它总是返回一个指针 - 指针的类型指的是指向数据的类型,而不是指针本身,它总是寄存器的大小。但是,在C ++中,它被强制转换它。

现在,malloc的一般语法是:

TYPE* pointer = malloc(n * sizeof(TYPE));

其中TYPE是某种类型。 sizeof应始终是一个间接级别,小于您要分配的指针。 (所以TYPE**给你一个TYPE*的malloc。 n是要分配的此大小的块数,因此如果要分配100个双精度,那就是n

无论如何,你已经声明double** queryPoint;所以你的第一个malloc应该是:

queryPoint = (double**) malloc(some_size*sizeof(double*));

这给了我们一个大小为some_size的指针数组。就像任何其他阵列一样,您可以根据需要realloc,尽管预先确定数量可能是理想的。然后,对于您希望分配的每一行,您只需从queryPoint中选择一个偏移量并分配该特定指针所指向的双精度数组,如下所示:

queryPoint[i] = (double*) malloc(sizeof_this_array*sizeof(double));

然后,通过两个下标访问2D数组中的特定点:queryPoint [x] [y];

正如其他人所说的那样,realloc是一个选项,但我建议你每次填充数组时都要加上一个固定的数量,或者只是加倍你的数量,因为内存是(相对)便宜的,这将是保存系统调用或六个。

现在,我已经讨论了指针等,所以我要绘制一个强制性的内存表,以便你可以看到它的样子:

|Address      | Contents      | Comments
|-------------|---------------|-------------------------
|0x12345      | 0x20000       | double** queryPointer
| ...         | ...           | ...
|0x20000      | 0x30000       | double* queryPointer[0]
|0x20001      | 0x30016       | double* queryPointer[1]
|0x20002      | 0x30032       | double* queryPointer[2]
| ...         | ...           | ...
|0x30000      | 0183737722122 | These together make up the floating 
|0x30001      | 0183737722122 | point at double queryPointer[0][0]
|0x30002      | 0183737722122 |
| ...         | ...           | ...
|0x30016      | 0183737722122 | These together make up the floating 
|0x30017      | 0183737722122 | point at double queryPointer[0][1]
|0x30018      | 0183737722122 |
| ...         | ...           | ...

指针只是一个包含地址的地址,因此0x12345只是指向第一个malloc的一组地址的开头。这是一个指针数组,所以只是一个包含内存地址的内存地址集合,它指向实际值,如0x3***范围所示。请注意,所有地址大小,数据大小和值表示都非常垃圾。

正在发生。

此外,请不要忘记为您分配的每个内存地址free()

答案 1 :(得分:3)

在开头初始化:

double **queryPoint = 0;
int qp_count = 0;

每次拨打电话:

// call realloc to make the space for points larger by one element
queryPoint = realloc(queryPoint, sizeof(double*)*(qp_count+1));

// allocate space for the new point
queryPoint[qp_count] = malloc(sizeof(double)*2);

// increase the point count
qp_count++;

请注意,您可以使用realloc来调整行的空间大小。另请注意,您应该添加错误处理。

释放你需要打电话的记忆:

for(int i=0;i<qp_count;i++)
    free(queryPoint[i]);

free(queryPoint);

答案 2 :(得分:0)

变量queryPoint每次为一个指针分配空间,该指针在索引0(queryPoint[0])处可用。您尝试在queryPoint[qp_count]添加内存。这个指数没有记忆。要修复,请使用尽可能多的指针分配queryPoint来读取文件。

int MAX_POINTER_COUNT = 10000 // whatever you choose
double** queryPoint=(double**)malloc(MAX_POINTER_COUNT * sizeof(double**));

一定不要写在数组末尾!这样做是一个潜在的漏洞溢出错误。 (特别是如果您阅读从外部提供的数据)。

答案 3 :(得分:0)

你走在正确的轨道上。 queryPoint基本上是一个数组数组。但是,每次循环时,都会将之前的queryPoint指针替换为新的指针double*。你真正想做的是用一个指针增长queryPoint

queryPoint = (double**)realloc(queryPoint, sizeof(double*)*(qp_count+1));

(请注意,要使其工作queryPoint,请将其初始化为NULL。)

此外,您的第二次分配应该是sizeof(double)*2,而不是sizeof(double*)*2

注意模式:在malloc(或realloc)内,我们有一个sizeof(TYPE)。然后将返回值强制转换为TYPE*。例如:

p = (double*)malloc(sizeof(double)*n);
pp = (double**)malloc(sizeof(double*)*n);

答案 4 :(得分:0)

泄漏token = malloc(40);行分配的空间;那不好。

您没有显示line的定义。

每次循环时,都会泄漏先前分配给queryPoint的空间。

您在queryPoint=(double*)malloc(sizeof(double**));上的投射是错误的;不应为double **queryPoint;分配double *。关于演员是否是一个好主意,意见分歧(不一定均匀)。

每次在第一个循环之后的循环中,您可以访问分配给queryPoint的区域之外的空间。

您初始化int qp_count = 0;,然后使用qp_count = 0;再次将其设置为零,其中两个分配中的一个就足够了。

循环中的第二个strtok()也可能正在寻找换行符。

您不会检查strtok()是否找到了令牌。您不检查atof()是否成功。 (实际上,无法检查atof();您可能需要使用strtod()。)

答案 5 :(得分:0)

您应该首先更准确地定义您要执行的操作。

您不知道文件中有多少行,因此您最初不知道二维数组必须有多少行。最初的问题/问题是错误的。二维数组不适合这种类型的条件。

链表似乎更合适。如果每行(行)只有两个值,则结构可能更合适,以便您可以将指针添加到下一个queryPoint对。

答案 6 :(得分:0)

您希望在此次通话中分配多少字节?

queryPoint=(double*)malloc(sizeof(double**));

malloc()实际给你了多少?

它为您提供了void *中的多个字节,在您的32位计算机上可能有8个。

这里发生了什么?

queryPoint[qp_count]=(double*)malloc(sizeof(double*)*2);

您正在向右存储到queryPoint中,覆盖malloc()在前一行中给出的指针。这是你想要的吗?

答案 7 :(得分:-2)

这就是你malloc二维数组的方式:

double (*two_dim_array)[ncols] = malloc(nrows * sizeof *two_dim_array);