user-0 提问: 关于多维指针的使用

回复:
user: user-0
content: 感谢大佬们  我明白了

user: user-1
content: LS都说了，补充一下 2 【triangle是二维指针，是怎么能够进行triangle[i][j]操作？vs是不能运行的，原因在于编译器不知道*triangle的数组长度有多大，没办法找到triangle[i][j]】，如果是这样，你的代码 if (1 == triangleSize)         return triangle[0][0]; //为什么就可以操作？i=0,j=0  所以问题不在于编译器知不知道长度有多少，这个长度是你自己保证的，如果长度没能保证，编译器只会数组越界进行非法操作。所以这些参数的指针的有效性以及数组长度是你自己去保证的，因为编译器不知道运行时就传入什么参数，所以只要你语法对，就可以编译。  3 你的cache[I]都知道malloc分配内存，为何就没有想到triangle_p[i]没分配内存？所以triangle_p[0][0];是非法的。

user: user-2
content: C99支持动态数组 Vs出错是因为他对c99标准不完全支持

user: user-3
content: 引用 楼主 盛祖吕 的回复:问题如下： 1.题解使用的c语言是标准c吗？为什么能用变量初始化数组长度 2.triangle是二维指针，是怎么能够进行triangle[i][j]操作？vs是不能运行的，原因在于编译器不知道*triangle的数组长度有多大，没办法找到triangle[i][j]，而如下操作是可以的，创建了一个一维指针数组，每一个一维指针都指向一块独立的内存空间  int** cache = (int**)malloc(sizeof(int*) * triangleSize); for (int i = 0; i < triangleSize; i++) { 	cache[i] = (int*)malloc(sizeof(int) * triangleColSize[i]); }  3.针对问题2中的问题，类似于本题的情况，如何才能优雅的实现对一个多维数组使用数组下标来操作。 	cache[0][0] = triangle_p[0][0];		//此处运行崩溃 1、这个是符合C99标准的语法，用变量初始化数组长度且是局部作用域的数组称为变长数组 2、triangle是二维指针，是怎么能够进行triangle[i][j]操作？这个是二维数组的基本操作，triangle[i]是一维指针，triangle[i][j]就是元素了 3、明显你只对cache的二维分配了空间，没有对triangle_p的二维分配空间就访问当然出错

user: user-1
content: 引用 5 楼 盛祖吕 的回复:[quote=引用 3 楼 qybao 的回复:]LS都说了，补充一下 2 【triangle是二维指针，是怎么能够进行triangle[i][j]操作？vs是不能运行的，原因在于编译器不知道*triangle的数组长度有多大，没办法找到triangle[i][j]】，如果是这样，你的代码 if (1 == triangleSize)         return triangle[0][0]; //为什么就可以操作？i=0,j=0  所以问题不在于编译器知不知道长度有多少，这个长度是你自己保证的，如果长度没能保证，编译器只会数组越界进行非法操作。所以这些参数的指针的有效性以及数组长度是你自己去保证的，因为编译器不知道运行时就传入什么参数，所以只要你语法对，就可以编译。  3 你的cache[I]都知道malloc分配内存，为何就没有想到triangle_p[i]没分配内存？所以triangle_p[0][0];是非法的。 不好意思贴错代码了 我之所以会说编译器不知道多少是因为如下例子： int a[2][2] = { {0,1}, {2,3} }; int **b = a; printf("%d\n", b[1][0]); 这样子运行的时候会崩溃，因为编译器不知道b[0]-b[1]间具体有多大的内存空间，所以必须显式的指定指针的宽度所以得写成以下这样才能正确运行 int a[2][2] = { {0,1}, {2,3} }; int (*b)[2] = a; printf("%d\n", b[1][0]); 那么问题来了   我的这个题目传入的参数数组的宽度不是定值，也就是说指定指针宽度得是个变值，而vs里又要求指针宽度不能是变量，这就很矛盾了，例如下面这样编译就会报错 int c = 2; int (*b)[c] = a;[/quote]  你没明白我的意思。我上面也说了，编译器不管长度，你不保证长度它就越界非法访问内存，所以这个参数传入是你自己保证的。 人家的题目又没有说main函数会给minimumTotal函数传入一个等长的二维数组（为了回答还去看了一下题目，下次直接贴题目不要链接），你怎么就自以为人家传入函数的参数是等长二维数组呢？ 比如  void printDoublePointer(int **p, int row, int *col) { //谁规定这里的p是等长的二维数组？p本身就是个不等长数组，1维长度row控制，2维长度col控制，很正常     int i, j;     for(i=0; i<row; i++) {         for (j=0; j<col[i]; j++) {             printf("%d ", p[i][j]); //这里的I，j是靠你保证的，你传入的参数不对，自然就会造成非法访问         }         printf("\n");     } }  int main() {     int n=5, i, j;     int **p = (int**)malloc(sizeof(int*)*n);     int *col = (int*)malloc(sizeof(int)*n);     for (i=0; i<n; i++) {         col[i] = i+1;         p[i] = (int*)malloc(sizeof(int)*col[i]);         for (j=0; j<col[i]; j++) {             p[i][j] = j+1;         }     }     printDoublePointer(p, n, col); //人家main函数这样传参数不行吗？谁规定一定用等长二维数组     free(col);     for (i=0; i<n; i++) {         free(p[i]);     }     free(p);     return 0; }

user: user-0
content: 引用 8 楼 user-4 的回复:数组不是指针  你用二级指针指向二维数组是错误的行为  属于对指针和数组理解错误 所以oj在调用我的函数进行传参的时候传入的是一个指针数组，而不是直接将一个二维数组传入喽 这样看起来就说的过去了

user: user-4
content: 数组不是指针  你用二级指针指向二维数组是错误的行为  属于对指针和数组理解错误

user: user-4
content: 引用 5 楼 盛祖吕 的回复:我之所以会说编译器不知道多少是因为如下例子： int a[2][2] = { {0,1}, {2,3} }; int **b = a; printf("%d\n", b[1][0]); 这样子运行的时候会崩溃，因为编译器不知道b[0]-b[1]间具体有多大的内存空间 这个崩溃和你说的内容毫无关系 假设 int* 和 int 都是 4个字节 假设 数组a地址是1000 b[1] 就是 *(b+1) b是1000  b+1是1004 1004是 a[0][1]的地址 b[1][0] 相当于 *(int*)a[0][1] 把a[0][1]这个int内容当成地址 并解引用 导致崩溃

user: user-0
content: if (1 == triangleSize)         return triangle[0][0]; //为什么就可以操作？i=0,j=0 这句话没报错是因为用例没运行到

user: user-0
content: 引用 3 楼 qybao 的回复:LS都说了，补充一下 2 【triangle是二维指针，是怎么能够进行triangle[i][j]操作？vs是不能运行的，原因在于编译器不知道*triangle的数组长度有多大，没办法找到triangle[i][j]】，如果是这样，你的代码 if (1 == triangleSize)         return triangle[0][0]; //为什么就可以操作？i=0,j=0  所以问题不在于编译器知不知道长度有多少，这个长度是你自己保证的，如果长度没能保证，编译器只会数组越界进行非法操作。所以这些参数的指针的有效性以及数组长度是你自己去保证的，因为编译器不知道运行时就传入什么参数，所以只要你语法对，就可以编译。  3 你的cache[I]都知道malloc分配内存，为何就没有想到triangle_p[i]没分配内存？所以triangle_p[0][0];是非法的。 不好意思贴错代码了 我之所以会说编译器不知道多少是因为如下例子： int a[2][2] = { {0,1}, {2,3} }; int **b = a; printf("%d\n", b[1][0]); 这样子运行的时候会崩溃，因为编译器不知道b[0]-b[1]间具体有多大的内存空间，所以必须显式的指定指针的宽度所以得写成以下这样才能正确运行 int a[2][2] = { {0,1}, {2,3} }; int (*b)[2] = a; printf("%d\n", b[1][0]); 那么问题来了   我的这个题目传入的参数数组的宽度不是定值，也就是说指定指针宽度得是个变值，而vs里又要求指针宽度不能是变量，这就很矛盾了，例如下面这样编译就会报错 int c = 2; int (*b)[c] = a;

user: user-0
content: 不好意思贴错代码了 上面的是我调试的代码，实际没有triangle_p这个指针  int minimumTotal(int** triangle, int triangleSize, int* triangleColSize) {     int** cache = (int**)malloc(sizeof(int*) * triangleSize);     int res = 99999999999;     if (1 == triangleSize)         return triangle[0][0];     else if (!triangleSize)         return -1;     for (int i = 0; i < triangleSize; i++)     {         cache[i] = (int*)malloc(sizeof(int) * triangleColSize[i]);         memset(cache[i], 0, sizeof(int) * triangleColSize[i]);       }     cache[0][0] = triangle[0][0];        //此处运行崩溃     for (int i = 1; i < triangleSize; i++)     {         for (int j = 0; j < triangleColSize[i]; j++)         {             if (0 == j)             {                 cache[i][0] = cache[i - 1][0] + triangle_p[i][0];             }             else             {                 cache[i][j] = MIN(cache[i - 1][j], cache[i - 1][j - 1]) + triangle_p[i][j];             }         }     }     for (int i = 0; i < triangleColSize[triangleSize - 1]; i++)     {         res = MIN(res, cache[triangleSize - 1][i]);     }     return res; }