C语言整理<三>数据类型(重要)

这次将所有数据类型做一个整理,作为C语言的结束篇。下一期就是数据结构与常见算法。

数据类型分类

基本类型整型短整型short2字节
整型int4
长整型long 4
长长整型longlong8
浮点型单精度float4
双精度double8
长双精度long double8
字符类型char1,汉字2
枚举类型enum
构造类型数组
结构体struct
共用体union
指针类型
空类型

 在C语言里面,变量必须先定义再使用。变量定义包括:数据类型,存储类型,作用域。

定义变量为:[存储类型]  数据类型 变量名;作用域是看定义在那个部分上了。

作用域

作用域就是定义变量所在的范围,不在这个范围不能用。所以不同的函数可以用相同名字的变量名。

局部变量:在函数或者语句块里面定义的变量。它的作用域就是这个函数或者语句块。

全局变量:就是在源文件里不在函数或者语句块定义的变量。作用域是整个源文件。也可以拓展到别的文件。

存储类型

存储类型是指变量在内存中的存储方式。

定义存储类型的目的是管理内存和资源,同时又定义了变量的生命周期,还有指定链接属性。

用户区

动态存储区
内存用户区静态存储区bss数据段
代码区普通数据段

图中的红色表示所属关系。

动态存储区存放一些动态存储的变量,在调用时分配内存并赋初值,调用结束释放内存。

auto:自动存储类,局部变量默认的存储类,声明的变量将在栈上分配内存,在栈上先进后出,栈里面存储函数调用的上下文信息,包括局部变量,返回地址和函数参数。生命周期起于被调用时,这时在栈上分配内存,终结于调用结束,释放内存。在被调用时赋初值,可以多次赋值。
寄存器
register:用于定义存储在寄存器中而不是 RAM (以后在单片机里面再讲这个)中的局部变量。不能对它应用一元的 '&' 运算符(因为它没有内存位置)。变量的访问速度更快,在需要频繁访问的变量上使用 register 存储类可以提高程序的运行速度。生命周期和auto一样,都是对局部变量的声明。但是寄存器有限,不足时会自动转化成auto型变量。

静态存储区这里只讲普通数据段。普通数据段存放静态变量,初始化的全局变量或者常量配内存,函数调用结束,释放内存。

在函数或者语句块外面的声明的变量就是全局变量,存储在静态存储区,但是还有两个关键字也可以进行说明。

static:静态存储类,声明的变量只分配一次内存,在程序的整个运行期间都存在,直到程序结  束。可以在函数外面用来声明全局变量,这时,只能在本源文件使用。但是也可以在函数里面声明局部变量(在编译时赋初值,如果没有赋值自动赋值0或者空字符),而且只能在函数内部使用,同时只在第一次初始化,之后都是在前一次调用的基础上进行调用,和AUTO型变量是不同的。
extern:外部存储类,声明的变量在其他文件中定义,在本文件中只声明,不分配内存。这样就可以将全局变量作用域扩展到别的文件里。

同时如果已经在函数里面定义了一个局部变量,则也可以通过这个关键字的在函数外声明,从而使这个变量的作用域变成整个源文件。成为全局变量。

volatile:易失性存储类,声明的变量在程序运行过程中可能被程序控制流之外修改,编译器不会对其进行优化。多用于以下情况:

1.变量被多个线程共享,防止编译器对其进行优化。

多线程:C语言实现多线程_c语言多线程-CSDN博客

2.变量在硬件中断服务历程(ISR)中被修改。如果在ISR中被修改,而主程序也可能访问,这种情况下应该声明。
const:常量存储类,声明的变量的值不能被修改。
restrict:限制指针存储类,声明的指针只能指向特定内存区域,而且是唯一的方式,别的指针无法修改这个指针所对应的内存里的内容。

数据类型

本文只列举一些特色的常用的数据类型。

1>数组

定义方式:数据类型 数组名[常量表达式];

需要注意的是数组元素下标从0开始。引用时逐个引用,A[0],A[10]。另一点值得注意的是数组元素都是相同数据类型。

二维数组

数据类型 数组名[常量表达式1][常量表达式2];

2>指针

首先来看直接访问和间接访问的概念。

直接访问,可以思考,当我们定义一个变量后,要存到用户区,每个变量是和一个地址对应的,所以也就是说有一个类似表的东西实现这种映射关系。在实际情况下,确实有这么的一个表,是在编译阶段时完成的。所以当我们直接使用变量时不用管到底存到了哪里。这就是直接访问。

但是当我们把变量的地址给了另一个变量,意味着使用这个变量时要通过这个存了这个变量地址的变量,这就是间接访问。

指针就是这种间接访问。

指针定义:类型说明符 *指针变量名;

双重指针定义:类型说明符 **指针变量名;

注意事项:1.当定义多个指针时可以在类型说明符后面写多个变量,但是必须带上*,否则只有第一个是指针,意义不对。

2.未经赋值的指针不能用,通过&加变量名将其地址赋值给指针变量。

3.根据*a_i=*&i=i,所以*和&是一个逆运算,相互抵消当遇见时。

4.可以改变指针的值,也可以用指针给指针赋值。但是注意的是这时候是指针名,别弄错。

指针与数组

C语言为一个数组分配一块连续的地址,数组名表示这块连续地址的首地址,即int*ptr=&array[0];

ptr,array,&array[0]是等价的。所以数组元素array[i]的地址就是ptr+i或者array+i。

数组指针和指针数组

数组指针是指一个数组的指针,也就是把一个数组的地址给指针变量。

类型说明符(*指针变量名)[长度];

类型说明符一维数组的数据类型,长度是一维数组的长度,一维数组的长度是数组指针的步长,括弧不可省略。

指针数组是数组的元素是指针,类型说明符 *数组名[长度];

类型说明符:指针数组元素指向的元素数据类型。

3>结构体

当很多元素的数据类型不一样时,使用构造类型。

struct 结构体名{

成员列表;

};

成员列表可以是各种不同类型的变量,一般形式是类型说明符 成员名;

结构体名和结构体变量

结构体名和结构体变量是不一样的,结构体变量有三种定义方法。

第一种 已经定义好结构体

struct 结构体名{

成员列表;

};

结构体名  结构体变量名;

第二种在定义结构时同时定义结构体变量

struct 结构体名{

成员列表;

} 结构体变量名1 ,结构体变量名2;

第三种在定义结构体时直接定义多个结构体变量

struct {

成员列表;

} 结构体变量名1 ,结构体变量名2;

同时结构体也可以嵌套。后面使用时就是一个数据变量类型自然也有数组指针。

typedef

为数据类型取别名。

typedef  原类型名 新类型名;原类型名可以是各种数据类型。

4>枚举类型

枚举类型是一种基本数据结构但是定义变量又和结构体一样。同样是第一种已经定义好结构体在定义变量,第二种定义同时定义变量……

当一个变量的值被限定在一个有范围的情况下用枚举。

enum 枚举类型名 {枚举值列表};

注意

1.不能赋值,是常量

2.枚举元素有默认数值,依次为0,1……例如:enum weekday{ sunday,monday}workday;

workday=monday;相当于workday=1;

3.可以进行关系运算,按照他们表示的数值比较。

5>共用体

union 共用体名{

成员列表;

};

和结构体不同的是每个成员共用一个内存空间,也就是同住一个屋子但是屋子不够大,一次只能住一个,所以内存空间大小是最大的成员的大小。变量定义和结构体一样的三种方式。

对共用体赋值时,起作用的是最后一次被赋值的成员,以前的存储单元中的内容被取代。

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值