2

C语言学习之存储类

 1 month ago
source link: https://www.biaodianfu.com/storage-classes-in-c.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在C语言中,存储类定义了变量/函数的范围(可见性)和生命周期。这些说明符放在编译器前以理解变量的工作方式。C语言中有以下类型的存储类:

storage-classes-in-c.png
  • 自动(Auto):这是所有局部变量的默认存储类。在函数体、循环体等内部声明的变量是自动变量。
  • 寄存器(Register):这是自动的变体类,它告诉编译器使用寄存器来存储变量,而不是RAM。
  • 静态(Static):指示编译器保留变量,即使超出了它的范围也是如此。它还指示编译器在程序启动时对变量进行初始化。
  • 外部(Extern):指示我们的变量是在程序的其他地方定义的,也就是说,这是一个已存在的全局变量的引用。
  • 类型限定符(Type Qualifiers):const, volatile, 和 restrict 是类型限定符,不是存储类,但它们也可以改变变量的存储类。

auto存储类

auto是C语言中的一个存储类,用于声明自动变量。这是所有局部变量的默认存储类。”auto”只能在函数内部使用,它是局部变量的默认类型。下面是一个简单的例子:

#include <stdio.h>
void function() {
int i = 0; // same as "auto int i = 0;"
printf("%d ", i);
int main() {
function(); // prints: 0
function(); // prints: 0
return 0;
#include <stdio.h>

void function() {
   int i = 0; // same as "auto int i = 0;"
   printf("%d ", i);
   i++;
}

int main() {
   function(); // prints: 0
   function(); // prints: 0
   return 0;
}

在这个例子中, i就是一个auto变量。当function()被调用时,变量i被初始化为0。当函数再次被调用时,i又被重新初始化为0。

需要注意的是,在C语言中,我们通常省略auto关键字,直接写变量的类型和名称。因为如果没有指定存储类,编译器默认变量为auto。

register 存储类

register是C语言中的一个存储类,用于建议编译器将某个变量存储在寄存器中,而不是RAM中。这样做的原因是,从寄存器中访问变量比从RAM中快得多。然而,这只是一个建议,编译器可能会忽略这个建议。

register只能用于局部变量和函数的输入参数。寄存器的数量是有限的,且可能已经被用于其他目的,因此并非所有请求都能被满足。

下面是一个使用register的例子:

#include <stdio.h>
void function() {
register int i; // "register" suggests to store "i" in a register
for (i=0; i<10000; i++) {
printf("%d ", i);
int main() {
function();
return 0;
#include <stdio.h>

void function() {
   register int i; // "register" suggests to store "i" in a register
   for (i=0; i<10000; i++) {
      printf("%d ", i);
   }
}

int main() {
   function();
   return 0;
}

在这个例子中,我们建议编译器将循环变量i存储在寄存器中。这样做是因为i将在循环中被频繁访问,将其存储在寄存器中可能会提高速度。

需要注意的是,对于现代的优化编译器,你可能不需要显式声明register,编译器会自动进行寄存器分配优化。

static 存储类

static是C语言中的一个存储类,它可以用于声明静态变量。

当变量被声明为static时,空间将在程序的生命周期内一直存在,即使超出了它的范围也是如此。同时,static变量在程序启动时只初始化一次。

static存储类有以下用途:

  • 如果在函数体内部声明静态变量,那么这个变量就会在函数调用之间保持其值。
  • 在函数外部声明的静态变量可以在整个文件中访问,而不仅仅是在声明它的函数中。这样,它们就像全局变量,但只能在一个文件中使用。

下面是一个使用static变量的例子:

#include <stdio.h>
void function() {
static int i = 0; // "static" means "i" keeps its value between function calls
printf("%d ", i);
int main() {
function(); // prints: 0
function(); // prints: 1
return 0;
#include <stdio.h>

void function() {
   static int i = 0; // "static" means "i" keeps its value between function calls
   printf("%d ", i);
   i++;
}

int main() {
   function(); // prints: 0
   function(); // prints: 1
   return 0;
}

在这个例子中,变量i是在函数内部声明的静态变量。尽管function()被调用了两次,但i在两次调用之间保持了它的值。

需要注意的是,如果static变量没有显式初始化,那么它会被隐式初始化为0。

extern 存储类

extern是C语言中的一个存储类,它用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当你使用extern时,对于变量或者函数的定义来说,你是在告诉编译器这个变量或者函数在别的地方已经定义过了,现在只需要使用就可以了。

下面是一个使用extern存储类的例子:

假设有两个C文件,file1.c和file2.c。

file1.c:

#include <stdio.h>
int count ; // Global variable, can be accessed by other files using extern
void main() {
printf("The value of count is: %d", count);
#include <stdio.h>

int count ; // Global variable, can be accessed by other files using extern

void main() {
   printf("The value of count is: %d", count);
}

file2.c:

#include <stdio.h>
extern int count; // count is defined in another file, this is just a declaration
void func() {
count = 5;
void main() {
func();
printf("The value of count is: %d", count); // prints: 5
#include <stdio.h>

extern int count; // count is defined in another file, this is just a declaration

void func() {
   count = 5;
}

void main() {
   func();
   printf("The value of count is: %d", count); // prints: 5
}

在这个例子中,count在file1.c中声明并定义,而在file2.c中,我们使用extern关键字来声明变量count。这告诉编译器,变量count是在别的地方定义的,只需要引用它就可以了。

注意,使用extern声明的变量,没有分配存储空间。其存储空间是在变量定义的地方分配的。

类型限定符(Type Qualifiers)

const,volatile和restrict被称为类型限定符,它们并不是存储类,但是它们可以影响变量的行为。

const

这个关键字让我们可以声明常量。常量是在程序执行期间不会改变的值。尝试改变常量的值会导致编译错误。

const int a = 10; // "a" is a constant, its value cannot be changed
a = 20; // Error
const int a = 10; // "a" is a constant, its value cannot be changed
a = 20; // Error

volatile

这个关键字用来告诉编译器,该变量的值可能会在外部被意外(不可预测的)改变,这样,编译器就不会对这个变量进行优化,每次引用时都会从其所在的内存中提取,而不会使用保存在寄存器中的备份。这对硬件访问操作、多线程编程等方面非常有用。

volatile int a = 10; // The value of "a" can be changed unexpectedly
volatile int a = 10; // The value of "a" can be changed unexpectedly

restrict

这个关键字是C99标准中引入的,用于告诉编译器,所有修改某个对象或者对象所指向的值的操作,都必须直接通过该对象来完成(也就是说,不存在其他途径可以用来修改该对象或者对象所指向的值)。这个关键字主要被用在指针类型中,能够帮助编译器进行更好的优化。

int arr[10];
int * restrict restp = arr; // restp is the only way to access arr for the scope of restp
int arr[10];
int * restrict restp = arr; // restp is the only way to access arr for the scope of restp

请注意,const和volatile可以同时应用于一个变量,例如const volatile int a;声明了一个既是const又是volatile的变量。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK