C语言 存储类型关键字详解 您所在的位置:网站首页 c语言存储区域有哪些类型和特点 C语言 存储类型关键字详解

C语言 存储类型关键字详解

2023-10-02 09:56| 来源: 网络整理| 查看: 265

今天我们重点说下auto,register,typedef,extern,和static。

让我们进入今天的学习吧!(今天也要加油哦)

在这里插入图片描述

1. auto(自动变量)

auto作为比较老的关键字,在C语言中使用的有限,简单说下语法吧。 auto:它很宽宏大量的,你就当它不存在吧,在缺省的情况下所有局部变量都是 auto 的。auto被叫做自动变量,就是变量空间自动申请释放,就是自动变量。

2 . static(静态变量)

static修饰的变量时,放在了静态数据区。 在上上篇博客中很详细说了,就不在赘述了。 static常考点

3.register(寄存器变量) 3.1 register语法

这个关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内 存寻址访问以提高效率。注意是尽可能,不是绝对。你想想,一个 CPU 的寄存器也就那么几个或几十个,你要是定义了很多很多 register 变量,没有那么多的寄存器让register用。

3.2 寄存器变量可以取地址吗?

各位读者大人,想一个问题,那么可以对寄存器变量进行取地址操作吗? 例 1:

register a = 10; printf("%p\n", &a); //error C2103 : 寄存器变量上的“&” return 0;

这个例子就证明了,register变量不可被取地址,为什么不可以被取地址呢? 因为地址是内存相关的概念,你要取地址也要在内存上取吧,不在内存怎么取地址呢?

举个例子帮助理解下: 这就像一个人开车闯红灯要扣6分,但是人家就没有驾照你咋扣分呢?

3.3什么情况下使用register修饰变量的?

1.局部变量,(全局变量会占据寄存器) 2.不会被写入的(一旦写入,就要返回内存,然后再被检测) 3.被高频读写的(高频读写的放入寄存器中,会更容易的让CPU拿到)

3.4 register的变量的细节

寄存器变量是可以被赋值的。 例 2:

int main() { register a = 10; a = 100; printf("%d\n", a);//100 return 0; }

寄存器变量的默认数据类型是int 在这里插入图片描述 在这里插入图片描述 也可以定义其他类型 例 3:

int main() { register char a = 10; a = 100; printf("%d\n", a);//a的类型是 char return 0; } 4.extern(外部存储变量) 4.1 extern作用

extern变量称为外部存储变量。extern声明了程序中将要用到但尚未定义的外部变量。通常,在C语言中extern主要负责的再头文件中的全局变量的声明,函数的声明。

4.2 extern的注意事项

首先extern声明外部符号的,在头文件中声明函数和全局变量的。 例 4:

extern int a; extern void fan();

那么再声明时可以初始化吗? 首先声明并非定义,定义时开辟的有空间,而声明中没有空间,所以声明不可以初始化。 声明时可以省略extern吗? 语法上不管是变量还是函数,不加extern好像都不会出错,但是就变量而言定义不初始化和声明是一样的写法 例 5:

int a;//声明 int a;//定义但不初始化

没有注释,各位读者能分清楚声明和初始化吗?我想不能吧。所以在声明变量时,必须要带上extern。

那么函数呢,是不是可以不带extern呢? 例 6:

void fan();//声明 void fan()//定义

从直观上是看可以看出来的,以分号结束的是声明,但是还是推荐大家声明函数时也带上extern。

声明可以多次吗? 可以多次声明,但是不可以多次定义。 举个例子: 你买彩票中奖了,你可以说很多次,但是就彩票中奖来说,你只中了一次,同理,声明可以多次,但定义只有一次。

5.typedef(特殊的存储类型) 5.1 typedef解释

typedef 的真正意思是给一个已经存在的数据类型(注意:是类型不是变量)取一个别名,而非定义一个新的数据类型。

5.2 typedef的使用

5.2.1 对结构体进行typedef 下面是结构体进行重命名之后的类型查看,来进一步判断是否typedef创建了新的类型。 例 7:

struct str//定义结构体 { int a; }; typedef struct str _str;//对结构体进行重命名 int main() { struct str ret = { 0 };//创建结构体变量 _str val = { 0 };//用typedef定义类型创建变量 struct str * p = &val;//把typedef的变量地址存进结构体指针中 return 0; }

调试查看类型可以看出类型是一样的。 typedef重命名 5.2.2 对数组进行typedef 例 8:

typedef int a[10];//定义一个类型 int[10] 名字是a int main() { int b[10] = { 0 };//定义一个数组,数组类型是 int[10] a c = { 0 };//用a定义一个数组,数组类型是a return 0; }

调试,查看类型,看出,a和b数组类型一样。

在这里插入图片描述

5.2.3 typedef对unsigned int重命名。 例9 :

typedef unsigned int _int; int main() { unsigned int a = 0; _int b = 0; return 0; }

调试看出,a,b类型一样 在这里插入图片描述 综上所述,可以看出typedef只是换了个名字,但是最终类型不变,有种换汤不换药的感觉。

5.3 typedef 和 define做比较

看个例子加深下理解 例 10:

typedef int* ptr_t; int main() { ptr_t a, b;//没初始化,不推荐大家写,只做研究 return 0; }

在这里插入图片描述 这里看出typedef定义两者的类型是一样的。

例 10:

#define PTR_T int* int main() { PTR_T a, b;//不推荐这样写,只做研究 return 0; }

在这里插入图片描述

define定义的可以看出不是一个类型,a是int*的,b是默认的int型。

得出结论 define 是定义一个宏来进行替换。 而typedef是把一个变量的名字换了。

6.总结存储类型关键字

这些存储类型关键字,上述也都说过了,他们或多或少的对一些变量或者函数的说呢过命周期和作用域,以及变量开辟空间相关,还有一个比较特殊的关键字typedef也归结到了存储类型关键字了。

重点来了 这些存储类型关键字不可以同时修饰一个变量

在这里插入图片描述 这是不可以的,数据只有一个存储类型,一个以上出现是不可以的。

下期预告

下期讲下volatile和sizeof,各位看官明天见

都看到这里了,给个三连吧 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有