数据与量_C语言快速入门与计算机二级备考
计算机内部的数据
- 各种数值在计算机中用机器数表示,机器码使用二进制(0和1)
数
-
带符号数
只有0和1,如何储存负数?将数字的最高位用于表示这个数的符号,0表示正数、1表示复数,这称为原码
占n个字节的数据类型,数字表达范围为:-2n-1~2n-1-1
n-1因为整个范围被划分两半以储存正数与负数,非负整数部分2n-1再-1因为零占了一位数
-
无符号数
如果想让一个数按原本的二进制数解读而不再划分一半表达负数,可以使用无符号数
具体的使用方法是在使用的数据类型之前加上
unsigned
即可例如:
//char是一个占一个字节,含8个位,用于表示整数的数据类型 char a = 255; //这时,由于255的二进制为11111111,二进制补码解读为-1,出现溢出,输出-1 unsigned char a = 255; //这时,char的范围不再划分以表达符号,于是255得以正确表达
- 使用unsigned的目的是便于进行纯二进制运算
- 当无符号数与有符号的负数同时运算时,无符号数将会被视作正整数,而比较大小时负数将更大
带符号数的表示
-
原码
一个数的正常二进制表示方式,最高位是符号(因此0的原码会有两种)
-
反码
正数的反码就是原码;负数的反码则是在原码基础上除了符号位外全部按位取反得到
-
补码
正数的补码就是原码;负数的补码则是在原码的基础上先除了符号位外全部按位取反得到,再在末位+1,有进位则产生进位;计算机储存整数使用补码
-
移码
用作浮点运算的阶码,无论正负,都是将原码的补码的首位(符号位) 取反得到偏远码
-
之所以要规定这些编码,是为了简化计算机对减法的处理,当两数相减时,就相当于被减数的补码加上减数的补码负数(改变符号位)
需要注意原码的最高位不参与运算,只用来表示符号;而其他编码最高位虽然同样代表符号,但是参与计算
小数的表示
在机器码中没有小数点,要如何表示小数?
-
定点表示法
将数分为纯小数与纯整数以及真值,约定纯小数的小数点位置在机器码的最高位前,纯整数则恰好相反,真值是机器码对应的实际数值
-
浮点数
与定点表示法相对,是小数点浮动的表示方法,类似科学计数法,表示方式为N=F×2E
其中E为阶码(带符号的纯整数,即指数部分),F称为尾数(带符号的纯小数,即表示数字的值)
浮点数所表达的数值范围由阶码决定,表示的数值精度由尾数决定,将各个部分组合起来就能够表示小数了
比如说101.011=0.101011×23
-
表示数字范围:
阶码使用移码格式:1位阶符,n位阶码:最大数2n-1,最小数-2n
尾码使用补码格式:1位数符,n位尾数:最小数-1,最大数1-2-n
-
如果阶码从移码改为补码,那么阶码部分将能够表示负数;如果尾数从原码改为补码,那么尾数部分将能够表示负数;但是因为占用了一位作符号,精度会下降
-
数据的大小
-
字长
CPU内寄存器一次能处理的数据,以及CPU和内存间总线一次所能传输的数据
这些决定了计算机的字长,通常为32位或者64位,即4个或8个字节
-
字节
一个字节通常就是指占8个位(二进制数)的位模式
例如:用一个字节储存整数
00000000→0;00000000-01111111→标识1到127;10000000-11111111→表示-1到-128
-
sizeof运算符
- 给出某个类型或变量在内存中所占据的字节数,例如:sizeof(int)
- 属于静态运算符,结果在编译时决定,在其中括号内不能做运算,例如:sizeof(a++)不能使a+1
数据类型
整数
-
char
占据1个字节(8个位)
-
字符
-
char不止是整数,也是一种特殊的类型:字符
使用单引号表示字符的字面量:例如'a','1'(字符类型的数字与整数的数字不同)
双引号用于字符串
输入输出使用 %c为占位符
-
C使用ASCII,用整数来代表一个字符,因此字符也可以进行运算
字母顺序排列,而大写字母与小写字母分开排列
可以通过
'a'-'A'
得到一个字母大写小写之间的距离(为32,大写字母在前,小写字母排在大写后,ASCII值更大)因此
A+'a'-'A'
可将大写转小写,a+'A'-'a'
把小写转大写c>='A' && c<='Z'
则可以判断字符c是不是大写字母
-
-
short
占据2个字节
-
int
一般占据4个字节,取决于编译器与CPU,
一个int通常表示一个字(int类型就是用于表达寄存器的大小的,如果是16位的系统则只占2字节,32或64位系统才是4字节)
因此,没有特殊情况只使用int(使用更短的类型不会提高处理速度)
-
long
一般占据8个字节(在32位机器上占据4个字节)
-
long long
占据8个字节
浮点数
-
float
占据4字节,同int,字长32个位;可以表示0/±inf(无限)/nan(不存在的浮点数);有效数字:7(超过此位将不再准确)
-
double
占据8字节,同long,字长64个位;可以表示0/±inf(无限)/nan(不存在的数);有效数字:15
没有特殊情况就只使用double
-
long double
-
浮点数的精度
-
数学中的数是连续的,但计算机只能表示一定范围内的数字,只能取一个最相近的数,因此存在精度误差,在现实某些情况的运用中,要使用整数进行运算以规避误差
-
例如:
float a,b,c; a = 1.345f; b = 1.123f; c = a+b; if (c!=2.468) printf("%f,%.10f",c,c); //最终结果是c不等于a+b,从输出中我们可以得知原因: //c=2.468000,但是在精确到小数点后十位的输出中,c=2.4679999352 //解决方法是,求两数相减的绝对值,然后看结果是否小于一个很小的数(由精度决定) fabs(a-b)<le-8;//float有7位有效数字,所以取小数点后8位
-
类型转换
-
所表达的数范围:char<short<int<float<double
-
当运算符两边的数范围不一样大时,会自动转换为较大范围的类型
-
对于printf,任何小于int的类型会转变为int;float会转变为double
但scanf不进行转换,要输入short,要使用%hd
强制类型转换
-
强制类型转换: (类型)值;例如:
(int)10.5
类型转换不改变原来的值,只是根据原值计算出该类型的值
优先级高于四则运算
浮点数运算的类型转换
-
两个整数运算的结果只能是整数,10与10.0在C中是完全不同的数
如果两个整数的运算出现小数部分,C会直接去除小数部分
-
表示带小数点的数就需要用到浮点数
浮点数指的是小数点浮动的数,是计算机表达非整数的方式
当浮点数与整数一起运算时,C会将整数转换为浮点数
int a,b; double c=(a+b)/2;//这样无法得到有小数部分的结果 double c=(a+b)/2.0;//这样的写法才行
-
小技巧:想让两个整数的运算输出浮点数(例如求平均数),可以让其中一个数乘1.0
枚举类型
-
与整数/浮点数这两种基本类型同为算术类型
用于取值有限且非常少量的整数数据,或者说需要一些排列起来的常量值,用枚举类型可以为每个值起名
-
程序中为了可读性与可维护性,用符号而非具体数字来表示程序中的数字,这个将符号和数字连接的过程就可用枚举
-
enum 枚举类型名{名字0,名字1,名字……};
仅仅给出名字,将会给出对应的值,其中的名字0对应int类型的0,名字1对应1……
-
声明枚举量可以举定值,例如
enum COLOR{RED=1, YELLOW, GREEN=5};
这这样YELLOW是2(跟着RED的1) -
例如:给予颜色数字代号以用于之后的
switch-case
const int red=0; const int yellow=1; const int green =2; //用枚举而不是定义独立的const int变量,在定义一些排比的符号量时更好用 enum COLOR{red, yellow, green}; enum COLOR{red, yellow, green,NumCOLORS}; //一个技巧:枚举量最后的NumCOLORS的值为3,正好就是前面所有枚举量的数 //因此在需要遍历所有枚举量或建立一个枚举量作下标的数组时就能用到 char *ColorNames[NumCOLORS]={"red", "yellow", "green"}; //这个字符串数组就用到了NumCOLORS的值,这样在增添新颜色时无须修改多处数字
逻辑类型
-
bool
-
#include <stdbool.h>
之后就可以使用bool true false,例如bool b = 6>5; printf("%d",b); //输出结果为1,这是因为C中没有真正的布尔值,依旧以整数形式表现
-
C语言将0作为假,非0作为真(注意,真不仅仅是1,2、3……都是真)
量
变量
-
定义变量
<变量类型> <变量名称> = <变量值>;
一般来说,变量的声明与定义同时进行,关于((20241111175020-m3e32bl "声明与定义区别"))
变量代表了内存中的某个存储单元,一经声明便开辟出存储单元存放变量
int a = 0; //这一行定义了一个变量:它的类型是int;名字是a;初始值是0 int a,b; //用逗号隔开一次声明多个变量
-
变量的名称是一种标识符
标识符只能用字母、数字和下划线构成
数字不可以出现在第一位,第一位必须是字母或下划线
C语言本身的关键字不可以用作标识符
-
-
赋值
在上面的代码中“=”是一个赋值运算符
与数学中的“等于”不同,“=”表示:要求计算机做一个动作将右边的值赋给左边的变量
因此 a=b 与 b=a 意义是相反的
-
尽量避免嵌套式赋值
int c =1+(a=b)//这样写容易出错,难以阅读
-
-
初始化
<变量类型><变量名称>=<初始值>;
在使用(出现在赋值运算符右边)一个变量之前应该先赋初始值
int a; int b; b=a+10; //这样写法是错误的,若是a被赋予了一个初始值便是正确的 int a=10 int b=200-a //只要在第一次使用前,可在任意位置定义变量,此处就在定义变量同时进行了计算
-
C是一种有类型的语言,所有变量必须:
- 使用前定义或声明
- 有确定的数据类型
- 只能存放数据类型指定的数据
- 运行过程中不能改变变量类型
-
常量
-
直接写入程序,固定不变的数,我们称其为直接量
-
与直接写入程序相比,更好的方法是定义一个常量
这样的好处是:他人更容易理解这个数的含义;以后更便于修改
-
当尝试对常量使用赋值修饰符修改将会报错
-
定义常量使用修饰符const
(实际上,这样被定义的仍是变量,只不过
const
的修饰使其无法被修改)const int A = 100; //这样就将A定义为了一个值为100的常量
-
符号常量
使用预处理器
define
-
例如:
#define A 100;
A就被定义为了符号常量,使用一个符号A来表示常量100,之后这个A不能再进行赋值
本质上在编译时将程序中所有的‘A’替换为100
-
量的分类
-
根据量的数据类型,可分为整型常量、实型常量、字符常量、字符串常量
-
整型常量
整型常量只能用不带小数点的数字表示
有时其尾部带一个字母L,表示这个常量的类型是long而非一般的int
尾巴带一个字母U表示该常量为unsigned无符号类型
-
实型常量
实型常量必须用带小数点的数表示
也可以使用科学计数法,格式为:尾数E指数,相当于尾数×10指数
指数不能是小数,字母E表示幂的底数为10,也用字母P表示底数为2
量的修饰符
-
前面已经提到
const
这个修饰符可以将变量变成“常量”,另外还有一些重要的修饰符,与变量的储存类别(分为静态类与动态类)有关 -
auto
自动;自动变量即局部变量,所有变量默认为此类型,因此少用
-
register
寄存器;将变量储存在寄存器而非内存中,访问速度将会提高(现代的编译器会自动决定是否该将变量储存在寄存器中以提高程序速度,因此少用)
因为不在内存中,因此不能求地址,指针和数组类别也不能使用这个修饰符
-
static
静态;在整个程序运行期间,静态局部变量占据永久的储存单元,地址不变,其初值在编译时赋予,如果没有初值,将会自动赋值为0
其将变量的生命周期扩展至整个程序,其值在退出一个函数后仍会保持
-
extern
外部;声明一个在其他地方定义的变量或函数,使其在当前文件中可用,例如:
//file1.c int i=0; //file2.c extern int i;//这样在文件2中也能使用文件1的i变量
同理也可以用在函数上,让一个文件可以调用另一个文件定义的函数
本文来自博客园,作者:无术师,转载请注明原文链接:https://www.cnblogs.com/untit1ed/p/18547795
本文使用知识共享4.0协议许可 CC BY-NC-SA 4.0
请注意: 特别说明版权归属的文章以及不归属于本人的转载内容(如引用的文章与图片)除外
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了