2016-12-24 61 views
2

我有我的表的第一行的一个问题的C 2维数组的malloc不保留一线

char **M = malloc(dim->lignes*sizeof(char)); 
for(i=0;i<dim->lignes;i++) 
{ 
    M[i]=malloc(dim->colonnes*sizeof(char)); 
    for(j=0;j<dim->colonnes;j++) 
    { 
     M[i][j] = fgetc(F); 
     printf(" "); 
     printf("%c",M[i][j]); 
    } 
    printf("\n"); 
    fgetc(F); 
} 

for(i=0;i<dim->lignes;i++) 
{ 
    for(j=0;j<dim->colonnes;j++) 
    { 
      printf(" "); 
      printf("%c",M[i][j]); 
    } 
    printf("\n"); 
} 

输出:

# # # # # # # # # 
# # # # # # # # # 
#   #  # 
# # #   # 
#    # 
#    # 
#    # 
#    # # 
#   # # # 
# # # # # # # # # 

P Õ h Õ Ç 
# # # # # # # # # 
#   #  # 
# # #   # 
#    # 
#    # 
#    # 
#    # # 
#   # # # 
# # # # # # # # # 

我不明白为什么第一打印是正确的,而不是第二。

+0

你的代码片段中没有二维数组,没有可指向一个的数组。如果你想要一个2D数组,请使用一个! – Olaf

回答

5
char **M = malloc(dim->lignes*sizeof(char)); 

这应该理解为

char **M = malloc(dim->lignes*sizeof(char *)); 

这本来是有效的,如果是这样,这是假设的例子,

char *M = malloc(dim->lignes*sizeof(char)); 

发现其中的差别在那里,与sizeof

对于单个指针,使用sizeof

对于双指针,使用sizeof *类型等。

+0

或在所有情况下使用'sizeof * p'(其中p是分配的变量) –

3

如在this answer中所述,以下内容不正确。

char **M = malloc(dim->lignes*sizeof(char)); // wrong with `sizeof(char)` 

不是sizeof(char*),使用sizeof *the_pointer_variable。这不像编码错误,更容易检查和维护。随着类型的变化,无需更改malloc()参数中使用的代码。

// OK 
char **M = malloc(dim->lignes*sizeof(char*)); 
// Better 
char **M = malloc(dim->lignes * sizeof *M); 
// Best 
char **M = malloc(sizeof *M * dim->lignes); 

最后,使用sizeof第一,有更复杂的计算优势。下面的第一个数学计算至少用size_t数学。第二次开始它的数学与rows * columns是什么类型。如果是int * int,可能发生的溢出可能不会发生在size_t数学中。

M = malloc(sizeof *M * rows * columns); 
M = malloc(rows * columns * sizeof *M); // Overflow with rows * columns? 
0

你碰到的问题,因为你char s,这是1个字节分配空间,当你需要为指针char,这是更大的(8个字节我的系统上)分配空间:

char **M = malloc(dim->lignes*sizeof(char)); 

你可以通过改变上述行来解决这个问题:

char **M = malloc(dim->lignes*sizeof(char *)); 

但是,也有一些常见的C成语,帮助您避免这种错误。 M是一个指向char的指针,所以你想为指向char的指针分配存储空间。但是*M(char *)类型的,所以你可以写:

char **M = malloc(dim->lignes*sizeof(*M)); 

您可以随时使用这个模式,这样可以让您明确指定该语句的右手侧类型。作为一个额外的好处,如果你曾经改变M的类型(例如(int **)),那么右侧仍然有效,所以这个成语比这个类型的显式语句更加健壮。

而且在你的代码,您有:

M[i]=malloc(dim->colonnes*sizeof(char)); 

但是,在C char保证是1个字节,所以sizeof(char)总是1.这使得利用sizeof操作冗余这里的。它被认为是很好的做法在这样的情况下,与sizeof分配:

M[i]=malloc(dim->colonnes); 

这减少了代码混乱。您可以改为考虑使用第一成语,这将仍然有效即使M变化类型:

M[i]=malloc(dim->colonnes*sizeof(*M[i])); 

或者是:

M[i]=malloc(dim->colonnes*sizeof(**M)); 
0

您的代码分配没有足够的内存为M。幸运的是,你可以在这个特殊情况下立即看到效果。

存储器布局是:

M:  00 00 00 00 00 00 00 00 00 
M[0]: 00 00 00 00 00 00 00 00 

我假设一个32位机在下面。然后M只有9个字节很大,但应该是36.所以当你在第4行读取时,分配到M[3]将被转换为memory[M + 4*3 .. M + 4*3 + 3] = …。索引表达式大于允许的9,但C运行时不关心这一点。相反,它会在分配M数组之后写入内存,这恰好是M[0]您的第一行字符。