黑马程序员—C学习笔记—static和extern修饰的函数和变量

———–Java培训、Android培训、IOS培训、.Net培训、期待与您交流!————

本节是个人学习过程中的笔记,供初学者一起学习,欢迎大家批评指正,留言参与讨论,谢谢。
本节内容是static与extern所修饰的函数和变量,还有一部分是对头文件的运用总结,所有细节都在代码和注释之中,代码如下:
static_extern.c

#include <stdio.h>
//#include "sub.txt"  //功能类似头文件,只有一个函数声明作用。

//#import <stdio.h>  OC用法,暂时不考虑

#include "static_extern_sub.h"

//内部函数和外部函数

//默认都是外部函数,可以省略extern

//void outterFuction_sub();
/*
 必须使用前声明,而且编译时带上从文件。如果使用头文件,就没必要这样去声明,而是直接使用,头文件的好处很多,虽然编译时也得带上从文件。头文件好处很多,能够更加清晰看到函数列表等
 PS:头文件作用
 1,头文件可以定义所用的函数列表,方便查阅你可以调用的函数;
 2,头文件可以定义很多宏定义,就是一些全局静态变量的定义,在这样的情况下,只要修改头文件的内容,程序就可以做相应的修改,不用亲自跑到繁琐的代码内去搜索。
 3,头文件只是声明,不占内存空间,要知道其执行过程,要看你头文件所申明的函数是在哪个.c文件里定义的,才知道。
 4,他并不是C自带的,可以不用。
 5,调用了头文件,就等于赋予了调用某些函数的权限,如果你要算一个数的N次方,就要调用Pow()函数,而这个函数是定义在math.c里面的,要用这个函数,就必需调用math.h这个头文件。
 头文件是上层应用程序与底层库或模块的桥梁。描述了库提供的功能函数。所以在库或模块的头文件中知描述模块对外界提供的函数接口及相关的数据结构。
 */

//int printf(const char*){return 0;};//重定义库函数失败

extern void outterFuction()
{
    printf("主文件外部函数被调用。\n");
}

static void innerFuction()
{
    printf("主文件内部函数被调用。\n");
}

int outter;

void testFuction()
{
    outterFuction();
    innerFuction();
    printf("Address of outter is:%p,outter = %d\n",&outter,outter);
    outterFuction_sub();
    //innerFuction_sub();//错误写法,无法访问其他函数的内部函数。

}

int outter;
int outter;
int outter = 10;
int outter;
//外部变量,无论写多少个重名,在哪个位置(不包括块内局部变量),在哪个文件,编译时都当做是同一个。
//int outter = 18;但是这种是不可以的,声明+赋值同时进行只能有一次,否则就会判定为重名,只是int outter;系统认为是声明,在outter声明之后的块内的使用可以直接使用,在outter之前的块使用前需要声明,如果不在块外声明,进去块里面声明,需要加上extern。也仅仅是这种情况必须使用extern,其他事情都可以省略掉咯。


//extern int outter_sub;
//如果头文件声明后,这里不需要再声明。如果头文件没有声明,这里就必须加上extern,否则编译时会因为同名报错。

//printf("testExtern = %d\n",testExtern);//这种写法是错误的

//int testExtern;  //后面变量,想提前使用,需要声明。可以放在函数前的这里,也可以放在函数体里面。

void testVariable()
{
    printf("由于outter_sub直接在本文件include的头文件中声明过,所以这里可以直接使用。\n");
    printf("outter_sub = %d\n",outter_sub);

    //    printf("outter_sub2 = %d\n",outter_sub2);//访问从文件静态变量,编译链接都没报错,但是却取不到正确地值,只能得到0
    //    printf("outter_sub3 = %d\n",outter_sub3);
    //    printf("outter_sub4 = %d\n",outter_sub4);
    printf("由于本函数体外部前面直接存在outter的声明,所以这里可以直接使用。\n");
    printf("Address of outter is:%p,outter = %d\n",&outter,outter);
    outter = 13;
    printf("Address of outter is:%p,outter = %d\n",&outter,outter);

    printf("由于本函数体内没有使用extern int outter;来声明outter,\n所以可以直接使用int outter = 23;来定义一个全新的局部变量outter。\n");
    int outter = 23;
    printf("Address of outter is:%p,outter = %d\n",&outter,outter);

//    int testExtern = 43;
//    printf("Address of testExtern is:%p,testExtern = %d\n",&testExtern,testExtern);

    printf("由于本函数体内使用extern int testExtern;来声明testExtern,\n所以可以直接使用testExtern,但是不能再用int testExtern = 23;来定义一个全新的局部变量testExtern。\n");
    extern int testExtern;
    printf("Address of testExtern is:%p,testExtern = %d\n",&testExtern,testExtern);
    testExtern = 53;
    printf("Address of testExtern is:%p,testExtern = %d\n",&testExtern,testExtern);
//    int testExtern = 43;  //因为有声明咯,所以不允许重名,如果声明放在外面,情况就类似于outter咯。
//    printf("Address of testExtern is:%p,testExtern = %d\n",&testExtern,testExtern);
}

int testExtern = 33;


int main()
{
    testFuction();
    testVariable();    
    return 0;
}

static_extern_sub.h

#ifndef STATIC_EXTERN_SUB_H
#define STATIC_EXTERN_SUB_H

//int outter_sub = 99;
//这里不能赋值,一赋值就会产生重名冲突
int outter_sub;

void outterFuction_sub();

//static int outter;
//static int outter_sub2;
//static int outter_sub3 = -1;
//static int outter_sub4;
//static void innerFuction_sub(){printf("头文件中static函数被调用。\n");};
//内部函数需要声明么?还是隐藏起来比较好,貌似不是对外的接口,不可调用
/*测试结论,用户直接写得xxx.h文件与xxx.c文件之间,编译器认为没有联系,它只执行include命令进行替换,所以如果在这里进行赋值或者函数实现操作,会被当做主文件中进行操作。
但是,用户角度,这个头文件是我们为了方便xxx.c文件中得声明,和自己查阅等便利才使用的,所以个人觉得头文件里面,1、只写xxx.c的外部函数和外部变量。2、只写声明,不能写实现。
*/
#endif

static_extern_sub.c

#include <stdio.h>  //不能因为主文件存在,而且他们一起编译,就省去这部分代码。虽然造成重复包含情况

static void innerFuction_sub()
{
    printf("从文件内部函数被开始调用。\n");
    extern int outter;
    outter = 120;
    printf("从文件内部函数改变主文件外部变量outter的值为%d\nAddress of outter is:%p,outter = %d\n",outter,&outter,outter);
    printf("从文件内部函数被调用完毕。\n");
}

void outterFuction_sub()
{
    printf("从文件外部函数被开始调用。并且调用从文件内部函数。\n");
    innerFuction_sub();
    extern int outter;
    outter = 122;
    printf("从文件外部函数改变主文件外部变量outter的值为%d\nAddress of outter is:%p,outter = %d\n",outter,&outter,outter);
    printf("从文件外部函数被调用完毕。\n");
}

//int outter = 10;// 这个会出错,这个不是声明,而是重新定义(声明+赋值同时进行),与主文件重名。

//static int outter = 9;//这个是可以的

int outter;//只是声明,那么就可以直接把主文件已经定义好的外部变量拿过来使用。

static int outter_sub2 = 7;
int outter_sub = 88;
static int outter_sub3 = 123;
static int outter_sub4= -98;

//void outterFuction(){} //外部函数不允许重名,即使是夸文件,所以多文件一起编译命名的问题很大。

程序运行结果如下:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值