C语言如何跨文件调用函数定义中声明的变量

  • 变量的作用域

我们知道,变量根据其作用域有全局变量和局部变量之分。全局变量作用域是整个文件,并且可以使用关键字 extern 达到跨文件调用的目的。但是局部变量值作用于它当前所在的块(即该变量所处最内层中括号之间的区域),当函数执行完并离开当前块后,局部变量及其所处内存空间的值就会销毁。

  • static 关键字

static + 变量声明 表示声明的这个变量是静态变量。静态不是说它的值不会被改变,而是它在内存中的地址静止不动,这也就意味着它的值从一直到函数运行结束之前,都不会被销毁。有趣的是,它声明的的变量只会声明一次,再次调用声明语句时,会自动跳过这条语句。如下面这段代码:

#include <stdio.h>
int main()
{
    int i = 0;
    printf("num1\tnum2\n");
    for(i = 0;i<4;i++)
      { static int num1 = 4;
        int num2 = 4;
        num1 ++;
        num2 ++;
        printf("%d\t%d\n",num1,num2)
      }
}  

运行结果为:


可以看到static初始化的num1变量,虽然我们放在循环中,看起来好像每次都会对变量进行初始化,但是结果却出人意表,num1在循环中没有受到初始化语句的影响,可以正常的进行运算。

  • 指针

指针是一个值为内存地址的变量(或数据对象)。指针本身是不具有内存的,但是它可以通过赋值,指向其他变量的地址进而得到它的内存。因为在计算机中,所有的变量都会有单独一块内存空间,所以理论上,只要使用指针指向变量的地址,就可以在程序的任何位置调用变量。所以,指针是我们实现跨文件跨域调用变量最重要的手段。

  • 使用指针跨文件调用变量

有了上面的基础,我们就可以开始调用变量了。为了表现跨文件的功能,我们定义一个头文件 test.h ,并且在里面放入一个函数声明 void Input(); ,然后我们再创建一个 test.c 文件来作为头文件的实现文件。最后在主文件 main.c 中调用它,函数代码如下:
test.c文件

#include "test.h"
int *ptr;        //声明一个外部指针用来调用变量
void Input()
{
     //初始化一个静态的数组
     static int nums[10] = {1,2,3,4,5,6,7,8,9,10};
     ptr = nums;  //将外部指针指向数组首地址
}

main.c文件

#include "test.h"       //引用我们自定义的头文件
#include <stdio.h>
   extern int *ptr;       //调用我们的外部指针
   int main()
  {
     Input();             //初始化数组并给指针赋值
     //下面打印结果,验证是否成功调用变量
     for(int i = 0;i<10;i++)
       {
        printf("%d\t",*(ptr + i));
       }
   }

运行结果为

可以看到,我们通过一个外部指针,在 Input() 函数内部将指针指向变量的地址,成功的调用了在其他文件的函数内部声明的数组/变量。
事实上,在这里面,static 关键字起到了至关重要的作用。我们尝试将nums[]数组改成普通的自动(auto)变量,看看运行结果:
运行结果为

可以看到,循环打印出来的是一片混乱的数值,这意味着指针向内存的数值已经被销毁了

时间: 2024-09-28 23:24:19

C语言如何跨文件调用函数定义中声明的变量的相关文章

cs文件-asp.net怎么跨文件调用另一个类的方法,求大神

问题描述 asp.net怎么跨文件调用另一个类的方法,求大神 例如: cs文件A class a { public a(){} public string stra(){} } cs文件B class b { public b(){} public string strb(){} } 现在我要在cs文件A里调用cs文件B的strb()方法,怎么写,求大神教,最好有个代码解释,谢谢! 解决方案 class a { public a(){} public string stra(){} public

浅析location.href跨窗口调用函数_javascript技巧

location.href这个东西常常用于跳转,location既是window对象的属性,又是document对象的属性. JavaScript hash 属性 -- 返回URL中#符号后面的内容 JavaScript host 属性 -- 返回域名 JavaScript hostname 属性 -- 返回主域名 JavaScript href 属性 -- 返回当前文档的完整URL或设置当前文档的URL JavaScript pathname 属性 -- 返回URL中域名后的部分 JavaSc

js实现iframe跨页面调用函数的方法_javascript技巧

本文实例讲述了js实现iframe跨页面调用函数的方法.分享给大家供大家参考.具体实现方法如下: 在项目中难免会遇到这样一个问题就是页面引入了IFrame并且需要父页面调用子页面函数或者子页面需要调用父页面函数.比如说:现在有两个页面parent.html和child.html.其中parent.html中含有IFrame并且IFrame指向child.html.现在需要在parent.html/child.html中调用child.html/parent.html的一个js方法.    具体的

Yii框架使用魔术方法实现跨文件调用功能示例

本文实例讲述了Yii框架使用魔术方法实现跨文件调用.分享给大家供大家参考,具体如下: 目前项目用yii框架,controller调用facade的方法,facade调用adapter的方法,adapter调用api的方法,api封装了sql方法,但是大部分情况下,只是单纯的调用,但限于目前项目的规则,都要写方法,而方法都是单纯的return,于是写了个demo,模拟了下. <?php class aApi { public static function tt1($name, $age) { p

怎么理解:c++不允许讲函数定义嵌套在另一函数定义中

问题描述 怎么理解:c++不允许讲函数定义嵌套在另一函数定义中 怎么理解:c++不允许讲函数定义嵌套在另一函数定义中能否简单说明一下,拜托! 解决方案 C++ 11开始,允许嵌套定义了,C++ 现在支持Lambda表达式. 解决方案二: http://www.cnblogs.com/haippy/archive/2013/05/31/3111560.html #include <vector>#include <iostream>#include <algorithm>

嵌入式软件-比较大的项目中,头文件中声明的变量和函数一般不太好确定前面是不是要加extern把

问题描述 比较大的项目中,头文件中声明的变量和函数一般不太好确定前面是不是要加extern把 比如这个.h文件中他用了一个ifdef,这个只是一个类似一个标志吧,任何程序里面都可以这样用吗,这是比较好的方式吗 解决方案 这是查看宏定义,判断是否define了这个宏.然后决定后面的各种定义.以endif结尾 解决方案二: ifdef你可以看做if..extern表示你函数定义在别的文件里.这里应该是为了防止冲突,通过宏值,决定是否是用本类中的该函数还是其他文件的相同命名的函数(起函数功能可能有所区

c语言编程-关于文件操作函数rename与remove

问题描述 关于文件操作函数rename与remove 我把文件指针都关闭了,可是调用rename(重命名文件)和remove(删除文件)函数都不起作用?把中间对文件的操作注释掉也一样,不知道哪里出了问题...两个函数的返回值都是-1,我也去查了原因,网络上讲解的好像都不是呀 解决方案 void onMenuDele(char *id) { FILE *p=fopen("f:employee.txt","r"); //打开文件 if(p==NULL) { printf

Shell中的函数、函数定义、作用域问题介绍_linux shell

说起函数调用,相信大家也不会陌生,然而对于初学Shell的我来说,Shell中函数调用方式却有点让我不太习惯,自己也走了不少的弯路,因为传递参数时出了一个很"自然"的错误,也让我吃了不少的苦头,所以总结一下Shell中函数的调用方法. 一.Shell中函数的定义 为了方便程序和管理和模块化并减少代码的重复,函数的确是一个好东西.而Shell中函数的定义有两种方法,如下: 复制代码 代码如下: function fname() {     statements: } 或 复制代码 代码如

嵌入式 C 语言的可变参数表函数的设计

首先在介绍可变参数表函数的设计之前,我们先来介绍一下最经典的可变参数表printf函数的实现原理.一.printf函数的实现原理在C/C++中,对函数参数的扫描是从后向前的.C/C++的函数参数是通过压入堆栈的方式来给函数传参数的(堆栈是一种先进后出的数据结构),最先压入的参数最后出来,在计算机的内存中,数据有2块,一块是堆,一块是栈(函数参数及局部变量在这里),而栈是从内存的高地址向低地址生长的,控制生长的就是堆栈指针了,最先压入的参数是在最上面,就是说在所有参数的最后面,最后压入的参数在最下