使用“include”使包含的任何子单元都可以访问数组;单位c;?

使用“include”使包含的任何子单元都可以访问数组;单位c;?,c,global-variables,C,Global Variables,如何确保从main.c调用的unit.c函数需要在main.c函数中正确声明数组 有没有办法在.c文件中全局声明变量?有没有一种不使用全局变量的聪明方法 例如: #include <stdio.h> #include "sub.c" int main(void) { int matrix[5][5]; matrix[5][1] = 5; Range(); } 现在出现的问题是,现在编译时会出现这样的错误 "In file included from mai

如何确保从main.c调用的unit.c函数需要在main.c函数中正确声明数组

有没有办法在.c文件中全局声明变量?有没有一种不使用全局变量的聪明方法

例如:

#include <stdio.h>
#include "sub.c"

int main(void)
{
    int matrix[5][5];
    matrix[5][1] = 5;
    Range();
}
现在出现的问题是,现在编译时会出现这样的错误

"In file included from main.c:
"sub.c:3:15: Error: Matrix not declared"

或者类似的东西。

良好的编程实践要求使用它们作为参数,因此选项是:

#include <stdio.h>
#include "sub.h"

    int main(void)
    {
        int matrix[5][5];
        matrix[5][1] = 5;
        Range(matrix);
    }

您应该有一个头文件,其中包含您需要调用和包含的函数的原型。我认为你没有包括.c文件

您还需要将参数传递给函数

如果需要跨文件访问变量,则需要使用extern variable。

因此,有几件事:

  • 不要包含.c文件(即源代码);这是一个坏习惯。对于这样一个小而简单的程序来说,这并不是什么大问题,但随着程序变得更大、更复杂,它将导致构建和维护方面的麻烦。您要做的是定义一个只包含函数声明的头文件,而不是函数的定义(主体),如下所示:
    /**
     * sub.h - declaration for Range function
     */
    #ifndef SUB_H  // include guards; prevents this file from being processed 
    #define SUB_H  // more than once for the same translation unit
    
    /**
     * Changing the type of Range to void since you aren't returning anything, and you 
     * aren't using the result of the function in your main function
     */
    void Range( /* parameter declarations, which we'll get into below */ ); 
    
    #endif
    
    void Range( int m[][5] )
    x = m[20][1];
    void Range(int m[][5], size_t rows);
    void Range(int m[][5] size_t rows, size_t i, size_t j)
    {
      if ( i < rows && j < 5 )
        printf("Your range is: %d\n", m[i][j];
    }
    
    然后您将
    #将此文件作为
    
    #include <stdio.h>
    #include "sub.h"
    
    int main( void )
    {
      int Matrix[5][5];
      Matrix[5][1] = 5; // this is an error; your array dimensions only go from 0 to 4
      Range( /* parameters, including Matrix, which we'll get into below */ );
    }
    然后表达式
    矩阵
    的类型是“5元素数组的5元素数组的
    int
    ”。由于此表达式不是
    sizeof
    或一元
    &
    运算符的操作数,因此它被转换为“指向
    int
    的5元素数组指针”类型的表达式,并且该值是数组第一行的地址(与数组本身的地址相同)。这意味着您的
    范围
    函数将声明为
    void Range( int m[][5] )
    x = m[20][1];
    void Range(int m[][5], size_t rows);
    void Range(int m[][5] size_t rows, size_t i, size_t j)
    {
      if ( i < rows && j < 5 )
        printf("Your range is: %d\n", m[i][j];
    }
    
    或者(第二个声明中的括号很重要;没有它们,
    m
    将被声明为指向
    int
    的指针数组,这不是我们想要的)。

    在函数参数声明的上下文中,
    ta[]
    ta[N]
    都被解释为
    ta*a
    ;也就是说,
    a
    被声明为指向
    T
    的指针,而不是
    T
    的数组。

    注意,由于您将数组的地址传递给函数,因此函数对数组所做的任何更改都将反映在调用方中;也就是说,如果
    Range
    更改
    m[4][0]
    的值,您将在
    矩阵[4][0]
    中看到更改后的值。

  • 因为我们只在声明中指定
    m
    的列数,所以我们希望传递一个额外的参数来指定行数。C不会对数组访问执行任何边界检查,这意味着您可以编写类似这样的代码,而不会在编译时收到警告或保证在运行时崩溃。因此,您需要自己进行边界检查,这意味着您需要知道数组除了列数之外还有多少行。您将为行数传递一个单独的参数:
    void Range( int m[][5] )
    x = m[20][1];
    code>Range(Matrix, 5);
    void Range(int m[][5], size_t rows);
    void Range(int m[][5] size_t rows, size_t i, size_t j)
    {
      if ( i < rows && j < 5 )
        printf("Your range is: %d\n", m[i][j];
    }
    

  • 上述方法的一个缺陷是
    m
    中的列数固定为5;此函数将无法处理其他大小的矩阵。如果你是 使用支持可变长度数组1的编译器时,可以使用变量来指定数组维度,而不是使用编译时常量。由于在数组声明中使用变量之前需要声明该变量,因此必须将原型编写为
    void Range( size_t rows, size_t cols, int m[][cols] );
    并将函数调用为
    Range(5, 5, Matrix);
    这将允许您在不同大小的矩阵上使用
    Range
    函数,例如: int M1[5][5]; int M2[9][9]; int M3[20][20]; ... Range(5, 5, M1); Range(9, 9, M2); Range(20, 20, M3); 你会称之为
    Range(&Matrix[0][0], 5, 5);
    Range(Matrix, 5, 4, 0);

  • 假设在
    矩阵[5][1]
    中存在一个元素;但是,C中的数组是0原点,这意味着这两个维度的索引都是从0到4。因此,要访问第五行的第一个元素,请参考
    矩阵[4][0]
    <代码>矩阵[5][1]
    超出了数组的范围。

    这还带来了一个问题,即您是否希望检查除
    m[4][0]
    之外的元素。如果希望函数访问数组的任意元素,则需要将行数和列数作为单独的参数传递;这与将数组的维度作为参数传递相结合,为您提供了一种确保您没有试图访问数组边界之外的元素的方法。因此,您的
    范围
    函数看起来像
    void Range( int m[][5] )
    x = m[20][1];
    void Range(int m[][5], size_t rows);
    void Range(int m[][5] size_t rows, size_t i, size_t j)
    {
      if ( i < rows && j < 5 )
        printf("Your range is: %d\n", m[i][j];
    }
    

  • 这就引出了我们的最后一项(最后);不要在代码中使用“幻数”。定义符号常量(预处理器宏)来表示矩阵中的行数和列数,而不是到处乱扔文字
    5
    。首先,如果您决定更改数组维度,则只需更新常量定义,而不必追踪文本
    5
    的每次出现,并确定它是否用于检查数组访问。将以上所有因素综合起来(假设您对
    Range
    仅处理特定大小的数组没有问题),我们得到:
    /**
    *sub.c-范围功能的实现
    */
    #包括
    #包括“sub.h”
    无效范围(int m[][COLS],大小\u t行,大小\u t i,大小\u t j)
    {
    if(i
    /**
    *main.c
    */
    #包括
    #包括“sub.h”
    内部主(空)
    {
    int矩阵[行][COLS];
    矩阵[4][0]=5;//假设我们知道4和0在
    范围(矩阵,行,4,0);//数组边界。
    }
    那么,你完全糊涂了吗


    1.C99编译器或C2011编译器,其中宏uuu STDC_NO_VLA_uuuu未定义或为0。一些C89编译器可能支持VLA作为扩展

    你能举一个例子(即使它不能编译)说明你想编译什么吗