提问者:小点点

在C和C++中,int**A和int A[][]作为函数参数有什么确切的区别?


我在编写一个带有矩阵的程序时遇到过这种情况,我使用int**m来声明我的矩阵--因为我需要动态分配,并且在函数中我使用了inta[][]。 我不记得有什么问题。 但是当我使用一个简单的m[6][6]矩阵和f(int**m,int**m2,rest params)时,我遇到了麻烦。

它编译了,当我运行这个程序(用GCC编写代码块)时,它就崩溃了。 我尝试通过添加printf()s进行调试,结果它在if()块处崩溃,在该块中崩溃是没有意义的。 将第一个函数参数从inta[][]修改为int*a[6],然后再修改第二个参数,我的程序在第一次尝试时工作了。 通过更仔细地调试我保存在int m[I][j]中的内容,并签入如果是垃圾值,而不是我正在放入的内容,我只是放入10来标记某些内容。

这么多年过去了,除非我在做这类事情时遇到GCC的编译器错误,否则我只是按照我想到的第一种方式编写。

使用int**int[][]声明变量/get函数参数(所有4种组合)背后的逻辑是什么? 我使用的大多数预定义函数都在函数头中使用int**

我知道int[][]不等于int**,它正确地是int*[],但是我遗漏了哪些东西呢? int[][]是一个多维数组,意思是数组的数组,所有3种编写方式看起来都是一样的。 对于int[][],它几乎总是要求只让第一个参数无效,就像对于intarray[][][],我需要将int arraya[][n1][n2][n3]放在函数参数中,对吗? 它需要知道除第一个数组以外的多维数组的维度,因为在声明函数参数时使用int*int[]可以没有问题?


共3个答案

匿名用户

在C和C++中,int**aint a[][]作为函数参数有什么确切的区别?

int*a。 这是一个指向int的指针。

int**a。 这是指向int的指针。

int a[]在所有其他上下文中,这将是一个数目不明的int数组,但作为函数参数声明符,它被调整为int的指针,即,在这种情况下,它与您编写的int*a相同。

int a[][]这将是一个数组的数组,数组的数目不确定,但由于数组元素不能是大小不确定的数组,因此这种类型的格式不正确。

int*a[]在所有其他上下文中,这将是指向int的指针的数组,但作为函数参数声明符,它被调整为指向int的指针的指针,即在这种情况下,它与您编写的int**a相同。

int(*a)[N]这是指向N个int数组的指针。

int a[][N]在所有其他上下文中,这将是一个由N个int数组组成的未指定数目的数组,但是作为函数参数声明符,它被调整为指向int的指针,即在这种情况下,它与编写int(*a)[N]相同。

一些例子:

void fun_1D(int*);        // argument is pointer to int
void fun_1D(int[]);       // same as above
void fun_1D(int[10]);     // same as above; note that 10 is ignored

int arr_1D[20];           // array of int
fun_1D(arr_1D);           // implicit conversion
fun_1D(&arr_1D[0]);       // same as above


void fun_2D(int (*)[20]); // note that 20 is not ignored
void fun_2D(int[][20]);   // same as above
void fun_2D(int[10][20]); // same as above; note that 10 is ignored

int arr_2D[20][20];       // array of array of int
fun_2D(arr_2D);           // implicit conversion
fun_2D(&arr_2D[0]);       // same as above

fun_1D(arr_2D[i]);        // implicit conversion
fun_1D(&arr_2D[i][0]);    // same as above


void fun_ptrs(int**);     // argument is pointer to pointer to int
void fun_ptrs(int*[]);    // same as above
void fun_ptrs(int*[10]);  // same as above; note that 10 is ignored

int *arr_ptr[20];         // array of pointers
fun_ptrs(arr_ptr);        // implicit conversion
fun_ptrs(&arr_ptr[0]);    // same as above

要记住一些简单的经验法则:

  • 数组不是指针。
  • 指针不是数组。
  • 写为数组的函数参数实际上不是数组。 它实际上被调整为指向此类数组的元素的指针。 在此调整之后,函数参数永远不是数组。 这不适用于除函数参数之外的任何其他上下文。
  • 并非每个类型都可以是数组的元素。 未指定长度的数组就是这样的类型。
  • 没有“数组未指定长度”类型的对象。 它们只能用于引用别处定义的数组的外部变量声明中,或者用于从数组的初始值设定项推导出实际大小的定义中,或者用于将数组调整为元素指针的函数参数声明中。

匿名用户

int **a

这是指向int的指针。

int a[][]

这是int数组的数组,但这是无效的,因为第二个数组的维度必须在声明时已知,即第二个数组必须是完整的,因为它不能在之后完成,就像那样

int a[][DIM]

匿名用户

C++继承了C的行为,即数组衰变为指针。

这种行为真的很有帮助,直到一个人撞到一个锋利的边缘,意识到有什么奇怪的事情在发生,然后一个人试图弄清楚它在做什么,测试出这种行为,意识到它有点疯狂。

但是保持冷静,一旦你意识到数组衰变为指针意味着什么,一切又变得有意义了。

这里有一个例子来说明差异。

static void func1(int** p) {
    (void)p;
}

static void func2(int (&a)[2][2]) {
    (void)a;
}

int main() {
    // x is a 2-dimensional array of int objects.
    int x[2][2] = {{10, 20}, {30, 40}};
    // x[0][0] is 10, and is at 0x1000 (say, for example)
    // x[0][1] is 20, and is at 0x1004
    // x[1][0] is 30, and is at 0x1008
    // x[1][1] is 40, and is at 0x100C

    // y is a 1-dimensional array of pointers.
    int* y[2] = { &x[0][0], &x[1][0] };
    // y[0] is 0x1000, and is at 0x1010 (say, for example)
    // y[1] is 0x1008, and is at 0x1018

    // x cannot decay into an int**, because it is not an array of pointers.
    // y can decay into an int**, because it is an array of pointers.
    func1(y);

    // x can be used for an int[2][2] reference parameter.
    // y cannot be used for an int[2][2] reference parameter.
    func2(x);
}

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c|c++|中|int|int|函数|参数|确切|区别)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?