C语言从头学26——函数说明符

一、extern 说明符

我们在阅读C、C++底层代码或是MFC代码时,会看经常到 extern 这个符号。对于多文件的项目,源码文件经常会用到其他文件声明的函数。这时,当前文件里面,需要给出外部函数的原型,并用 extern 说明该函数的定义来自其他文件,以避免重复声明。

它的作用与使用 #inlude "自定义文件名" 作用类似,但 extern 的优点是不用考虑函数在哪个自定义文件中,只要在函数原型前加上 extern 就可以使用,用法简单。

二、static 说明符

static 翻译过来是静态的、不变的意思。默认情况下,每次调用函数时,函数的内部变量都会重新初始化,不会保留上一次运行的结果。static 用于函数内部声明变量时,表示该变量只需要初始化一次,不需要在每次调用时都进行初始化。static 修饰的变量初始化时,初值只能为常量不能为变量。如果不使用 static 说明符,要达到这种效果,就需使用全局变量,造成函数结构不完整。举个例子说明static的作用:

cpp 复制代码
#include<stdio.h>
void myCount(void)
{
    static int count = 0; //int count被static说明
    count++;
    printf("函数myCount被调用次数:%d次\n", count);
    return;
}
int main(void)
{
    for (int i = 0; i < 5; i++)
    {
        printf("i=%d", i);
        myCount();
    }
    getchar();
    return 0;
}

运行结果:

i=0函数myCount被调用次数:1次

i=1函数myCount被调用次数:2次

i=2函数myCount被调用次数:3次

i=3函数myCount被调用次数:4次

i=4函数myCount被调用次数:5次

从运行结果可以看出static说明符的作用。

static 还可以用来修饰函数本身,表示该函数只能在当前文件里使用,如果没有这个关键字,其他文件也可以借用 extern 说明符来使用这个函数。也就是说,如果某个函数不想让所在文件之外使用,那就加上static即可。但如果使用 #include "自定义文件名" 方法把带有static修饰的函数包含进来,则是可以使用那个函数的。

三、const 说明符

函数参数里面的const说明符,表示函数内部不得修改该参数变量。比如:

cpp 复制代码
#include<stdio.h>
void func(int* pInt)
{
    *pInt = 100;
    return;
}
int main(void)
{
    int a = 50;
    int* p = &a;
    printf("运行func函数前:a=%d\n", a);
    func(p);
    printf("运行func函数后:a=%d\n", a);
    getchar();
    return 0;

// 执行结果:

运行func函数前:a = 50

运行func函数后:a = 100

从上面例子中看到,函数 func() 本是一个无返回值的函数,但是由于它的运行,把外面的变量 a 的值给改变了。如果这不是我们希望的,如何避免呢?就是在函数声明的参数前加上 const,这样如果函数中再有改变 *pInt 指向的情况,编译时系统会报错 "表达式必须是可修改的左值"。上例可声明为:

cpp 复制代码
    void func(const int* pInt);

上述声明方式只是限制了 *pInt 不能更改,如更改就报错。但我们更改pInt,程序并不报错,如果我们希望 pInt 也不能更改,那就在 pInt 前也加上const。

const 说明符再加上指针很易把人绕糊涂,但我们只要把握一个原则即可:即 const 在谁前面谁就不能修改,修改就会报错。补充一点:以往在提到"诸如 int* p"时,一般总是作 "int与*" 结合的理解,在对 const 的理解上,可以把 "*与p" 放到一起理解就容易 "const 在谁前面谁就不能修改" 这句话了。

const的使用还可以扩展到函数返回值,以 "指针传递" 方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能赋值给加 const 修饰的同类型指针; 如赋给没有加 const 的指针,编译即使勉强通过也会给一个 "C4090" 的warning。

相关推荐
Tyler_TXZ1 小时前
C++C语言之——二叉树
c语言·开发语言·数据结构·c++·二叉树
小羊先生car1 小时前
F429-HAL-RS485(回环/双机实验)(2026/8/16)
c语言·单片机·嵌入式硬件·软件构建
白狐_7984 小时前
408 数据结构|线索二叉树两题详解:先序线索化后的空链域 + 中序前驱/后继判断
c语言·数据结构·链表
GeekZHR4 小时前
C语言指针进阶补充6:动态内存管理、mem系列内存函数、复杂指针声明,一次补齐指针的“三大盲区“
java·c语言·算法·指针
caimouse4 小时前
ReactOS 图形系统分析(43):API 裁剪 — cliprgn.c
c语言·开发语言
caimouse6 小时前
ReactOS 图形系统分析(36):位块传输 — bitblt.c
c语言·reactos
Tyler_TXZ6 小时前
C++C语言之——树
c语言·c++·算法·
小羊先生car6 小时前
F429-HAL-Can总线(回环及双机实验)(2026/8/15)
c语言·单片机·嵌入式硬件·软件构建
caimouse7 小时前
ReactOS 图形系统分析(38):区域子系统 — region.c
c语言
嵌入式阿蔡7 小时前
STM32时钟树详解:配错一个全乱套
c语言·stm32·单片机·嵌入式硬件