📜  C |存储类和类型限定符|问题8(1)

📅  最后修改于: 2023-12-03 15:13:46.954000             🧑  作者: Mango

C语言中的存储类和类型限定符

C语言中,存储类和类型限定符是用来改变变量的存储位置和属性的关键字。存储类包括auto、register、static、extern四个关键字,类型限定符包括const、volatile两个关键字。下面将一一介绍这些关键字的用法和作用。

存储类
auto

auto是C语言中默认的存储类。在函数内部定义的变量默认为auto类型,其存储类一般不需要明确指定。auto关键字可以显式地声明一个自动变量。

auto int a;

auto关键字的作用是告诉编译器将变量存储在栈中,当函数调用结束后,这些变量的内存空间将被释放。注意,在C++中auto有不同的含义,表示自动类型推断。

register

register关键字用于声明寄存器变量。它告诉编译器将变量存储在CPU的寄存器中,以提高访问速度。

register int a;

需要注意的是,register只是给编译器提示,是否真的将变量存储在寄存器中,取决于编译器的决策。

static

static关键字用于指示编译器将变量存储在静态存储区中。静态存储区的生命周期与程序的生命周期相同,即程序开始时进行分配,结束时释放。static变量在程序运行期间一直存在,而不会因为函数的调用而被重复创建。

void func() {
    static int a = 0;
    a++;
    printf("%d ", a);
}

int main() {
    for (int i = 0; i < 5; i++) {
        func();
    }
}

在上面的函数中,变量a每次调用增加1,但由于被声明为static变量,所以每次输出的都是递增的数值序列。

extern

extern关键字用于声明变量或函数是在程序其他地方定义的。它告诉编译器在程序其他位置寻找该变量或函数的定义。常见的情况是将函数的定义分散在多个文件中。使用extern关键字可以在一个文件中声明函数的原型,在另一个文件中定义函数实现。

// func.h
extern void func();

// func.c
void func() {
    printf("Hello, world!\n");
}

// main.c
#include "func.h"

int main() {
    func();
}

上面的示例中,func函数的原型声明保存在func.h中,实现保存在func.c中。在main.c中包含func.h文件,直接调用func函数。

类型限定符
const

const关键字用于声明一个变量为只读,即该变量的值不能被修改。const变量通常应该在声明时进行初始化,并且只能在运行时给它一个新的值。

const int a = 10;
int b = 20;

int fun1(const int *p) {
    // *p = 30; // 编译错误
    // a = 20; // 编译错误
    return *p + b;
}

int main() {
    printf("%d\n", fun1(&a)); // out: 30
    return 0;
}

fun1函数中,const int *p表示p指向的变量是只读的。如果试图修改p所指向的变量,编译将会报错。同样,试图修改a变量的值也会导致编译错误。

volatile

volatile关键字用于告诉编译器,该变量的值可能会在程序执行期间发生变化,因此不要对该变量进行优化。通常用于在多线程或信号处理等异步事件的处理中。

volatile int flag = 0;

void handler() {
    flag = 1;
}

int main() {
    signal(SIGINT, handler);
    while (flag == 0) {
        // do something
    }
    printf("Signal caught!\n");
    return 0;
}

上面的示例中,flag变量是在信号处理函数中被赋值的,但该变量没有被使用,编译器可能会优化掉这个变量的赋值操作。为了避免这种情况,可以使用volatile关键字。

总结

C语言中的存储类和类型限定符是用来改变变量存储位置和属性的关键字。存储类包括auto、register、static和extern四个,类型限定符包括const和volatile两个。熟练掌握这些关键字可以有效地提高程序的性能和安全性。