【问题标题】:Function to calculate sum of matrix gives error - [Error] array type has incomplete element type计算矩阵总和的函数给出错误 - [错误] 数组类型的元素类型不完整
【发布时间】:2020-03-31 15:07:32
【问题描述】:

计算矩阵总和的函数给出以下错误 - [错误] 数组类型的元素类型不完整

谁能解释我做错了什么。

代码如下:

  #include<stdio.h>

  int some_tab(int t[][],int n,int m);
  int main(){

    int tab[100][100],i,j,n,m;

    printf("\ndonner le nombre de lignes : ");

    scanf("%d",&n);
    printf("\ndonner le nombre des columns : ");
    scanf("%d",&m);

    for(i=0 ; i<n  ;i++){  
      printf("\nLigne %d: \n",i+1);
      for(j=0 ; j<m ;j++){  
          printf("\n donner le nombre numero %d :  ",j+1);
          scanf("%d",&tab[i][j]);   

       }
     }      

    printf("\nla somme du tableau est %d :  ",some_tab(tab,n,m));

    return 0;
  }

  int some_tab(int t[][],int n,int m){

        int i,j,s=0;

        for(i=0;i<n;i++){  
            for(j=0;j<m;j++)                                 
                 s = s + t[i][j];                                 
         }
        return s;
    }

【问题讨论】:

  • 将函数更改为int some_tab(int **t,int n,int m) 可能会修复。
  • @Punycode 小心!尽管像 int arr[n] 这样的一维数组“衰减”到像 int* p 这样的指针,像 int arr[n][m] 这样的二维数组 不会 衰减到 int** pp - 它也会衰减到单级指针(指向arr[0][0])!

标签: c arrays types element


【解决方案1】:

你的函数应该是这样的:

int some_tab(int t[][100],int n,int m)

将二维数组传递给函数时,您需要提及列。 您可以像这样全局声明列:

#include <stdio.h> 
const int COL = 100;
...

您可以使用指针。像这样:

void some_tab(int *t, int m, int n){
   int i, j; 
      for (i = 0; i < m; i++) 
        for (j = 0; j < n; j++) 
          printf("%d ", *((t+i*n) + j));
}

【讨论】:

  • 除非n 与调用例程中指定的等效维度完全匹配,否则您的第三个示例将不起作用!如果不是,i*n“列偏移”将是错误的。
【解决方案2】:

当您将具有多个维度的数组作为参数传递给函数时,只有 第一个(最左边)维度可以具有未知大小(空[])。这是必需的,因为计算给定元素的地址的方式。

例如,在这段代码中:

char array[10][20];
char b = array[3][2];

变量array 占用连续 200 (10 x 20) 字节长的内存块。元素array[0][0] 的地址(显然)与数组的基地址相同。要获得array[1][0] 的地址,编译器需要向该基地址添加一个值:在这种情况下,该值将是第二维(20)的size;同样,对于array[2][0],地址将是第二维大小的两倍,依此类推。

当我们开始更改 second 索引时,我们只需将该索引的实际值添加到为第一个索引计算的“偏移量”中。因此,如果我们调用数组的基地址ADDR,那么在上面的示例中,b 将在ADDR + 20 x 3 + 2 处被赋予char 的值。

但是,在您的 some_tab 函数中,编译器不知道 t 数组的第二维的大小是多少 - 那么它如何计算用于元素 t[i][j] 的适当地址偏移量? (请注意,编译器可以处理不知道第一维大小的问题,因为该大小从不用于计算元素的地址!)

为了解决这个问题,在您的情况下,最简单(尽管不一定是最佳)方法是给第二个维度一个固定大小 em> 即: (a) 大到足以处理代码必须处理的所有情况; (b) 在整个代码中100% 一致使用。所以,你可以使用这个:

int some_tab(int t[][100], int n, int m);

int main {
    int tab[100][100], i, j, n, m;
    //..
    printf("\nla somme du tableau est %d :  ", some_tab(tab, n, m));

但是,以下内容将严重失败,因为它中断了上面的 (b) 点:

int some_tab(int t[][200], int n, int m); // Change 100 to 200 for bigger space?

int main {
    int tab[100][100], i, j, n, m; /// This is now WRONG because tab has different 2nd dimension size!
    //..
    printf("\nla somme du tableau est %d :  ", some_tab(tab, n, m));

*注意:我在这里使用了一个char 数组来保持解释的简短,因为char 类型的大小正好 1 个字节。对于其他类型,任何元素的计算偏移量将简单地乘以该类型的大小。*

编辑:当我第一次发布时,我无法测试下面的(更好的)代码,因为我被“限制”使用 MSVC 本机 C 编译器(它使用了一个非常古老的语言标准,禁止它) .但是,现在我已经能够使用clang 进行测试,我可以确认以下代码可以按预期编译和工作。

这样做是使用 knownvariable 维度的数组,在运行时传递给 some_tab 函数-时间(编译器仍然可以正确计算每个元素的偏移量,但是,它不是使用 fixed 乘数作为第二维,而是使用 variable(在这种情况下,论点m)。

请务必阅读我添加的 cmets,用三斜杠 (///) 标记:

#include<stdio.h>

int some_tab(int n, int m, int t[n][m]); /// We MUST pass the "n" and "m" arguments FIRST!
int main()
{
    int i, j, n, m; /// NOTE: Declaration of "tab" MUST be moved ...
    printf("\ndonner le nombre de lignes : ");
    scanf("%d", &n);
    printf("\ndonner le nombre des columns : ");
    scanf("%d", &m);
    int tab[n][m]; /// ... to AFTER we know the actual values of "n" and "m"!!
    for (i = 0; i < n; i++) {
        printf("\nLigne %d: \n", i + 1);
        for (j = 0; j < m; j++) {
            printf("\n donner le nombre numero %d :  ", j + 1);
            scanf("%d", &tab[i][j]);
        }
    }
    printf("\nla somme du tableau est %d :  ", some_tab(n, m, tab)); /// Change argument order!
    return 0;
}

int some_tab(int n, int m, int t[n][m])  /// Note that this matches the pre-declaration!
{
    int i, j, s = 0;
    for (i = 0; i < n; i++) {
        for (j = 0; j < m; j++)
            s = s + t[i][j];
    }
    return s;
}

请随时要求任何进一步的澄清和/或解释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 2014-01-31
    • 1970-01-01
    相关资源
    最近更新 更多