2017-04-05 32 views
1

工作指针,我有以下两个功能:C编程 - 函数中使用与多维数组

double** transpose(double **a, int r, int c){ 
    static double trans[100][100]; 
    int i,j; 
    for(i = 0; i < r; i++) 
     for(j = 0; j < c; j++) 
      trans[j][i] = a[i][j]; 
    return trans; 
} 

double(*matrixMultiply(double a[10][10], double b[10][10], 
    int rowA, int colB, int colARowB))[10]{ 
    static double c[10][10]; 
    int i, j, k; 
    for(i = 0; i < rowA; i++) 
     for(j = 0; j < colB; j++){ 
      c[i][j] = 0; 
      for(k = 0; k < colARowB; k++) 
       c[i][j] += a[i][k]*b[k][j]; 
     } 
    return (double*) c; 
} 

虽然我明白的算法,能有人给我解释一下什么这两个函数返回(类型,指针。 ..)?第二个似乎返回数组,但我认为在C函数不能返回数组...

掌握这些指针真的很困惑......

而且为什么是阵列(transc)声明为静态?据我所知,当你声明一个变量或函数与静态它不能被导入用于另一个文件,但这是在这里肯定不是这种情况...

+2

'double **'是**不是**二维数组,并且不能指向一个。指针不是数组。不,你不能将数组传递给函数。但是你可以传递指向数组的指针。 – Olaf

回答

3

这两个函数都试图返回指针数组。两者都是这样做是错误的并且无法在我的系统上编译。

除了当它是sizeof或一元&运营商的操作数,或是使用在声明初始化字符数组文本字符串,类型“的T N元件阵列”的表达将被转换(“衰减”)转换为类型为“指向T的指针”的表达式,并且表达式的值将是该数组的第一个元素的地址。

transpose函数中,我们返回表达式transtrans具有类型“012-的100-元素阵列”,其中T是“100-元素阵列double”。它不是sizeof或一元&操作符的操作数,所以它被转换(“衰减”)为“指向T”类型的表达式,在这种情况下,它是“指向100个元素的数组double”(double (*)[100]) ,不是“指向double的指针的指针”,(double **)。

编译器应该抱怨那个函数。矿确实,像这样:

gcc -c -std=c99 -pedantic-errors -Wall transpose.c 
transpose.c: In function âtransposeâ: 
transpose.c:7: error: return from incompatible pointer type 

matrixMultiply功能,c具有类型“的double 10元件阵列的10个元素的阵列”,其中“衰减”到“指针至10个元素的数组的double” (double (*)[10])。第二个函数具有正确的返回类型 - double (*)[10] - 但他们搞砸了由return语句铸造cdouble *,我们得到了相同的错误面前:

gcc -c -std=c99 -pedantic-errors -Wall matrixMultiply.c 
matrixMultiply.c: In function âmatrixMultiplyâ: 
matrixMultiply.c:11: error: return from incompatible pointer type 

他们刚才写的

return c; 

和一切都会好起来的。

来读取第二函数定义的方法如下:

 matrixMultiply       -- matrixMultiply 
     matrixMultiply(     )  -- is a function taking 
     matrixMultiply(/* some params */)  -- some parameters (omitted for brevity) 
     *matrixMultiply(/* some params */)  -- returning a pointer 
     (*matrixMultiply(/* some params */))[10] -- to a 10-element array 
double(*matrixMultiply(/* some params */))[10] -- of double 

注意,唯一的原因要么功能有工作(一旦类型问题理顺了)的一个希望是,无论transc被宣布为static,这意味着它们的生命周期遍及整个程序,而不仅仅是它们各自功能的生命周期。没有那个static关键字,他们在它们的封闭函数返回后不再存在,那些指针将变为无效

这不一定是好的做法 - 这些功能不再是可重入的,也不是线程安全的。最好将目标数组作为参数传递给函数,但请注意,指向10元素数组的指针与指向11元素数组的指针是不同的,不兼容的类型 - 如果必须处理数组不同数量的列,这可能会变得棘手。沃拉斯可以与帮助:

void transpose(int r, int c, double arr[r][c], double trans[c][r]) 
{ 
    ... 
} 

假设你有VLAS可用(你应该对C99和C2011系统,虽然他们已经在C2011已经取得可选)。如果你不......这会变得更加困难。

+2

返回一个指向静态对象的指针的另一个问题,就像这里所做的那样,可能会出现意外的混叠。在OP的情况下,这是一个特殊的风险 - 如果其中一个函数的返回值作为后续调用中的参数传递回该函数,那么实际行为不可能是预期的。或者,如果对任一函数执行单独和独立的调用,则可能会惊奇的是之前的调用返回的指针指向不同的数据。 –

+0

非常感谢您的回答,以及您花时间写下这些内容的时间。现在很清楚。我对功能上的错误感到抱歉,但在我的辩护中,他们不是我的。我从昨天的编程课程复制粘贴它们。似乎老师没有注意......哦,好吧。 – ROBlackSnail

+0

@ROBlackSnail:对于那些自己被教导得很差的人来说,C几乎一律教好,而数组/指针语义学是大量错误信息和不良习惯转移的地方之一。这不是一个很好的*学习*资源,但将C语言标准的[当前在线草案](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)如果没有别的,它会告诉你如何东西*假设*工作。 –