我想通过使用简单的无效函数“assignTable”将二维字符数组“table”初始化为两个预定义的二维字符数组“A”和“B”之一。然而,虽然数组在“assignTable”中获得了正确的值,但分配的值似乎并没有转移到主函数中。我怀疑指针有问题。
你能告诉我我做错了什么吗?
#include <stdio.h>
#include <stdlib.h>
char A[10][10] = {
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'},
{'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'},
{'U', 'V', 'W', 'X', 'Y', 'Z', '.', ',', '!', '?'},
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'},
{'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'},
{'U', 'V', 'W', 'X', 'Y', 'Z', '.', ',', '!', '?'},
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'},
{'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'},
{'U', 'V', 'W', 'X', 'Y', 'Z', '.', ',', '!', '?'},
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}
};
char B[10][10] = {
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'},
{' ', 't', 'a', 'b', 'c', 'f', 'g', 'z', 'j', 'm'}
};
void printTable(int rows, int columns, char table[rows][columns])
{
for (int i = 0; i < rows; i = i + 1)
{
for (int j = 0; j < columns; j = j + 1)
printf("%c", table[i][j]);
printf("\n");
}
printf("\n");
}
void asssignTable(char* table, char* table_identity)
{
if (table_identity[0] == 'A')
table = A;
else if (table_identity[0] == 'B')
table = B;
printf("In the function ""assignTable"":\n"); // does work
printTable(10, 10, table);
}
int main()
{
char (*table)[10];
asssignTable(&table, "A");
printf("In main :\n"); // does not work
printTable(10, 10, table);
return 0;
}
必备知识:
char*
与 char(*)[columns]
和 char [rows][columns]
没有任何共同之处,因此不能使用。char(*)[columns]
是指向一维数组的指针。尽管在遍历二维数组时可能会用到它。char table[rows][columns]
的第一个元素是 char [columns]
类型。指向这种类型的指针是char (*)[columns]
.修复方法是像这样重写函数:
void asssignTable(int rows,
int columns,
char (**table)[rows][columns],
const char* table_identity)
{
if (table_identity[0] == 'A')
*table = &A;
else if (table_identity[0] == 'B')
*table = &B;
printf("In the function ""assignTable"":\n");
printTable(rows, columns, **table);
}
rows
和 columns
因为我们想使用与您的 printTable
功能一致的 API。char table [rows][columns]
,因为它会衰减为 char (*)[columns]
并且将该指针分配给某物不会影响调用者。我们必须使用指向指针的指针——在本例中是指向二维数组的指针。 (此语法与普通指针相当一致。)*table
取消对指针的引用,让我们可以访问在 main() 中使用的指针。我们将这个指针设置为指向二维数组的地址&A
等printTable(rows, columns, **table);
通过两次取消引用我们得到一个数组char [rows][columns]
之后它将像往常一样衰减为指向第一个元素的指针,因为我们实际上永远无法按值将数组传递给函数。来电代码变为:
char (*table)[10][10];
asssignTable(10, 10, &table, "A");
printf("In main :\n");
printTable(10, 10, *table);
答案真的很简单:C 是一种严格“按值传递”的语言。因此,请考虑以下程序:
void assign(int a) {
a = 5;
}
int main() {
int x = 0;
assign(x);
printf("%d\n",x);
}
希望很明显,该程序将打印“0”,而不是“5”。这是因为 x 的 value 被传递给了
assign
。
现在,考虑一个非常相似的程序:
int globalArray[] = {1,2,3};
void assign(int *p) {
p = globalArray;
}
int main() {
int *array;
// dynamically allocate array and initialize to {5,6,7}
// ...
assign(array);
print_array(array); // this is a pretend function
}
值得注意的是,
array
只是一个值(内存地址),就像int x
在上一个程序中是一个值一样。因此,assign
函数实际上并没有改变任何东西。
相反,你可以做类似的事情
int globalArray[] = {1,2,3};
void assign(int** arrayPointer) {
*arrayPointer = globalArray;
}
另一件需要注意的事情是,堆栈分配的二维数组与动态分配的二维数组的排列方式不同。