二维数组通过指针

我想创建一个存储排列序列的动态数组,这样

order[0][]={1,2,3} order[1][]={2,1,3} order[2][]={2,3,1} 

假设顺序[m] [n],m =排列数,n =项数,m和n是实时识别的。

我做了以下,发现指针地址重叠,导致值存储不正确。 如何通过双指针正确使用动态数组呢?

 void permute(int num_permute, int num_term, int** order) { int x, y; int term[5]; /* debug only */ for(y=num_term, x=0; y>0; y--, x++){ term[x] = y; } fprintf(stderr, "\n"); printf("order%12c", ' '); for (x=0; x<num_permute; ++x) { printf(" %-11d", x); } printf("\n"); for(y=0; y<num_permute; y++){ printf("%-5d%12p", y, (order+y)); memcpy(&(order[y]), term, sizeof(term)); for (x=0; x<num_term; x++) printf(" %12p", order+y+x); printf("\n"); } } int main(){ int y, z; int** x; x = (int*) malloc(5*5*sizeof(int*)); permute(5, 5, x); printf("\n"); printf("x "); for(z=0; z<5; z++){ printf(" %2d ", z); } printf("\n"); for(y=0; y<5; y++){ printf("%-4d", y); for(z=0; z<5; z++){ printf(" %2d ", *(x+y+z)); } printf("\n"); } free(x); return 0; } 

结果:订单[0] [1]和订单[1] [0]指向同一地址……其他人也是如此。 以行为主轴,列为次要列:

订单0 1 2 3 4           
 0 0x100100080 0x100100080 0x100100084 0x100100088 0x10010008c 0x100100090
 1 0x100100084 0x100100084 0x100100088 0x10010008c 0x100100090 0x100100094
 2 0x100100088 0x100100088 0x10010008c 0x100100090 0x100100094 0x100100098
 3 0x10010008c 0x10010008c 0x100100090 0x100100094 0x100100098 0x10010009c
 4 0x100100090 0x100100090 0x100100094 0x100100098 0x10010009c 0x1001000a0

 x 0 1 2 3 4 
 0 5 5 5 5 5 
 1 5 5 5 5 4 
 2 5 5 5 4 3 
 3 5 5 4 3 2 
 4 5 4 3 2 1 

源代码:
代码将类似于:

 #include  int **array; array = malloc(nrows * sizeof(int *)); if(array == NULL) { fprintf(stderr, "out of memory\n"); /*exit or return*/ } for(i = 0; i < nrows; i++) { array[i] = malloc(ncolumns * sizeof(int)); if(array[i] == NULL) { fprintf(stderr, "out of memory\n"); /*exit or return*/ } } 

概念:

array是指向指针的指针:在第一级,它指向一个指针块,每行一个指针。 第一级指针是第一个被分配的指针; 它有nrows元素,每个元素都足以容纳pointer-to-intint *pointer-to-int 。 如果分配成功,则用指针(也从malloc获得)填充指针(它们的所有nrows )到ncolumns的int数,即该行数组的存储。

图片描述:

如果您将情况可视化为以下情况,则很容易掌握:

指向指针数组的指针作为多维数组

考虑到这一点,示例代码可以重写为:

 void permute(int num_permute, int num_term, int** order) { int x, y; int term[5]; int* ptr = NULL; for (y=num_term, x=0; y>0; y--, x++) { term[x] = y; } printf("\n"); printf("order%12c", ' '); for (x=0; x 

代码示例仅模拟多维数组,并且不正确。 要查看出现了什么问题,首先要考虑在声明多维数组时会发生什么:

 int foo[3][5]; 

这将分配一个大小为3 * 5 * sizeof(int)的连续内存区域。 在诸如foo[i]类的表达式中, foo被转换为int [5]指针,然后应用索引运算符。 换句话说, foo[i]相当于*( (int (*)[5])foo) + i) 。 每个foo[i]将被视为具有5 * sizeof(int)的大小。

    x,y:0,0 0,1 0,2 0,3 0,4 1,0 
 foo  - > |  1 |  2 |  3 |  4 |  5 |  1 | ......
         < -  5 * sizeof(int) - >

在示例代码中创建x时,您正在复制此类型的多维数组。 你正在使用的索引表达式( *(order + y + x) )是错误的,因为它没有正确处理order[y]的大小: order + 1 + 0 == order + 0 + 1 ,是您在示例输出中看到的问题。

正确的表达式是:( (order + num_term * y)用于第y 排列, *(order + num_term * y + x)用于元素order[y][x]

这表明样本中存在另一类错误。 对于这种模拟的多维数组,数组类型实际上是指向单维数组的指针。 声明的xorder类型应该是int* ,而不是int** 。 这应该通过示例代码应该生成的类型警告来加强:

  • x分配空间时,指针的类型( int* )与x的类型不匹配
  • 当打印x的元素时, *(x+y+z)的类型与格式“%d”不匹配。

但是,虽然模拟多维数组可以节省空间,但在使用时更容易出错(除非您编写一个函数来处理索引)。 像Als’这样的解决方案可能更安全,因为您可以使用标准索引操作符。

如果你有C99(或C11),用指针数组模拟一个2D数组是一个完全的过度杀伤。 只是用

 void permute(size_t num_permute, size_t num_term, unsigned order[][num_term]); 

作为你的函数签名,并在main分配你的矩阵

 unsigned (*order)[m] = malloc(sizeof(unsigned[n][m])); 

另外,正如您在上面的示例中所看到的,我建议您使用语义正确的类型。 尺寸总是最好用size_t ,你的排列值看起来好像永远不会消极。 也许对于这些你也应该从0开始计算。

以下代码段为给定的行和列创建了一个2d矩阵。 请将此作为调试程序的参考。

 #include  #include  int main() { int row, column; int **matrix; int i, j, val; printf("Enter rows: "); scanf("%d", &row); printf("Enter columns: "); scanf("%d", &column); matrix = (int **) malloc (sizeof(int *) * row); if (matrix == NULL) { printf("ERROR: unable to allocate memory \n"); return -1; } for (i=0 ; i<----------- data ----------- ----------------------------------------------------------------- | | | | | | .. | | | | | | | .. | ----------------------------------------------------------------- | ^ | | |-----------------| header points to data area */ /* Output: $ gcc 2darray.c $ ./a.out Enter rows: 10 Enter columns: 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 $ */