3.C基础_数据类型

数据类型概述

在计算机的内存中存放了很多的二进制数据,数据类型就是管理这些数据的含义。比如下面的内存数据,尽管内存中的数据是完全一样的,但数据类型不同,实际代表的数值含义也不同。

sizeof关键字

sizeof可以获取数据所占的空间的字节数,返回值为长整型long,单位为字节。

使用方法:

  • sizeof(变量、数据类型关键字)
  • sizeof 变量

各种数据类型(类型修饰符)

1、整型

整型数据有五种:char、short、int、long、long long 以及这五种对应的unsigned形式。

下面是整型的总汇表:

数据类型名称

所占空间 (字节)

占位符取值范围
char(signed char)

有符号字符

1%d-2^7-1~2^7
unsigned char无符号字符1%c0~2^8-1
short(signed short)有符号短整型2%d-2^15-1~2^15
unsigned short无符号短整型2%u0~2^16-1
int(signed int)有符号整型4%d-2^31-1~2^31
unsigned int无符号整型4%u0~2^32-1
long(signed long)有符号长整型4、8%ld...
unsigned long无符号长整型4、8%lu...
long long(signed long long)有符号长长整型8%ld-2^63-1~2^63
unsigned long long无符号长长整型8%lu0~2^64-1

long型的大小与计算机系统的位数有关。32位系统对应的是4字节、64位系统对应的是8字节

2、字符型

字符型数据也是一种整型,它对应的类型为unsigned char。0~255中的每一个数字对应一个字符,这个字符的规定可以在ASCII码表中查询得到。

在Linux中,可以使用" man ASCII "来查询ASCII码表:

ASCII码表的字符分类:

  • 通讯、控制类字符:00H~1FH,共32个,有些无法显示在屏幕上
  • 符号、数字、字母:20H~7FH,共96个,全部都可以显示在屏幕上
  • IBM制定的扩充字符:80H~FFH,共128个,这些是非标准的ASCII码

定义相关特点:

字符型实质是整型,对应的是ASCII码。因此下面的定义效果实际上是一样的:

char val = 'A'; //以字符赋值变量
char val = 65;  //以字符对应的ASCII码赋值变量

常用字符的ASCII码:

  • a~z:97~122
  • A~Z:65~90
  • 0~9:48~57
  • 空格:32
  • 换行符\n:10

常用字符转换方法:

  • 大写字母与小写字母转换:±32(97-65 = 32)
  • 整型数字与字符数字转换:±48(0的ASCII码为48)

3、浮点型(实型)

浮点型数据有三种:float、double、long double

下面是浮点型的总汇表:

数据类型名称所占空间 (字节)占位符精度(小数点后几位)
float单精度4%f6
double双精度8%lf15~16
long double长精度>=8与编译器有关%Lf>=15~16

3.1 浮点型的表示

浮点型可以用小数来表示,也可以使用科学计数法表示,具体定义如下:

float val = 0.08;//正常的小数表示
float val = 8e-2;//科学计数法 8*10^-2

3.2 浮点型的内存形式

浮点型的内存存放形式遵循IEEE 754标准,具体标准如下:

对于E,这个称为偏移的阶码、移码。float的偏移量为127,double的偏移量为1023

下面以9.625为例,手算float类型的内存形式,具体计算过程如下:

下面是辅助计算的网址及操作方法:

Base Convert: IEEE 754 Floating Point

3.3 浮点型的比较判断注意点

如果浮点型的小数部分的处理是循环的(就是第一步进制转换时,小数部分*2取整步骤一直乘不尽),那么float与double类型的值是不一致的,这个原因是因为在内存中的M部分保存的数值不一样,精度缺失也不一样。下面以2.2和2.25为例:

在代码中的体现如下:

  • float与double变量比较

  • float与常数比较(常数默认为double型,加上 f 变为float型)

因此浮点数的比较不能直接使用 == 进行比较,而是使用求差的方式进行比较,具体代码如下:

4、布尔型

布尔变量是一个逻辑值,下面是布尔变量的表:

数据类型名称所占空间(字节)占位符取值范围
_Bool布尔1%d0、1
  • 布尔类型只有0、1,非0数赋值给布尔变量会变为1,0赋值给布尔变量还是0。
  • 所占空间为1字节,用第0位来表示0、1,其余7位不使用。

在 " stdbool.h "中,定义了布尔类型的一些宏,具体如下:

#define bool _Bool /* _Bool是关键字,bool只是别名不是关键字 */
#define true 1
#define false 

下面用一个例子来验证布尔的运算,代码和运行结果如下:

5、缺省型void

void是缺省型,代表没有类型。通常用法如下:

  • 用于函数前,代表没有返回值
  • 用于指针类型void*,代表通用指针类型,可以指向任何类型的数据

数据类型转换

数据类型的转换有自动类型转换和强制类型转换,自动类型转换还包括赋值操作时的转换、二元运算时的转换,数据类型的转换框图如下:

1、自动类型转换

1.1 赋值操作

在赋值操作时,等号右边的变量类型会自动转变成等号左边的变量类型,当右边类型精度比左边类型精度大时,会产生损失精度的问题。

/* 赋值时,数据类型转换 */
int a;
a = 3.14;//a为int,3.14为double,赋值时3.14会转成int变成3,产生了精度损失 

1.2 二元运算

二元运算就是有两个参数的运算,如加、减、乘、除等。

二元运算时自动会向精度高的类型转换,转换路径如下:

简单的验证代码如下:

/* 二元运算时的数据类型转换 */
int a = 50;
double b = a*0.3;/* a为int,0.3为double. a会先转为double再与0.3相乘 */

2、强制类型转换

强制类型转换就是在变量前写上" (变量类型) ",即可将该变量的类型进行转换。

例如在除法中,需要保留精度,具体代码如下:

/* 未强制转换 */
int a = 100;
int b = 3;
printf("%.2lf",a/b);
//a,b都为int,运算之后为33.333舍弃小数部分,即33,精度损失

/* 进行强制转换 */
int a = 100;
int b = 3;
printf("%.2lf",(double)a/b);
//a被强转为double,运算时b会自动转为double,最终结果为double型33.33,精度不丢失

数据定义时的前缀

0、概述

数据定义时,有一些前缀,比如前面的int、char这种,也有一些像const、auto这种。这些前缀分为3类:类型修饰符、类型限定符、存储类型。

类型修饰符:

类型修饰符就是定义数据类型。

如:int、char、float等

类型限定符:

类型限定符用来进一步定义变量的使用方式或属性,但不影响变量的基本类型

如:const、volatile、restrict

存储类型:

存储类型定义了变量的生命周期和作用域。

如:auto、static、extern、register 

相关名词概念:

  • 变量的作用域:变量能够被使用的范围;针对的是程序编译链接阶段
  • 生命周期:变量创建(分配存储空间)到变量销毁 (释放存储空间)之间的时间段(即变量的存在时间);针对的是程序的执行阶段;
  • 初始值:不同的存储类型,默认的初始值不同

1、const

1.1 const修饰变量

const是一个类型限定符,可以让变量变为只读常量,这样通过一般的赋值方式就不可以改变变量的值。

定义可以为:" const int a; "  或者 " int const a; "

 const修饰的变量修改值,可以通过指针的方式来修改。

1.2 const修饰指针

const修饰指针,可以规定*p、p是否进行修改。

具体内容在:博文8.C基础_指针基础-优快云博客中"其他指针-const修饰的指针"中

2、auto

auto是一个存储类型,它是一种默认情况。当定义变量时什么都不写时,其实就是auto类型。

比如定义" int a "这实际上就是" auto int a "

auto说明的变量只能在某个程序范围内使用,即:auto的作用对象是局部变量,因此auto不能对全局变量进行修饰。对于auto,无初始值的情况下,它的初始值是一个不确定的数。

3、register 

register是一个存储类型,它可以让局部变量不在内存中开辟空间,而是存储在寄存器中。

一般是将高频使用的局部变量加上register来提高代码运行的效率,但实际上这些工作都是编译器自动进行。

register只是程序员的主观想法,当CPU的寄存器没有足够空间时,会自动变为auto修饰。同时,过多的register也可能导致程序运行速度降低,因为占用了过多的寄存器,使得真正的运算能够使用的寄存器变少,从而导致运行速度降低。

注意:因此register修饰的变量存储在寄存器中,C中的地址指的是内存中的地址,因此register修饰的变量不能够使用指针去指向它

4、static

static是一个存储类型,它可以将变量变为静态存储变量,用于定义全局变量或局部变量。默认的初始值为0。

对于局部变量,被static修饰后,不会在栈中开辟空间,而是存放在静态存储区,地址是固定的,因此函数退出后释放栈空间,不会影响静态局部变量。

对于全局变量或函数,被static修饰后,代表只能当前文件下使用该全局变量或函数,其他文件通过extern并不能找到该全局变量或函数。

5、extern

extern是一个存储类型,被称为外部参照引用型。当希望在一个文件去使用另一个文件定义的全局变量或函数时,需要在变量或函数前加上extern去声明。(函数前可以不加)

extern只是声明,编译时并不会分配内存,而是在链接阶段将其与实际的定义进行关联。

注意:static修饰的全局变量或函数,extern声明后并不能找到该全局变量或函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值