c语言知识的重新整合(一)

简介: 以下关于c语言学习均使用的是VS2022,它是一个集成开发环境(IDE):一般包括代码编辑器、编译器、调试器和图形用户界面等工具。它的优点是安装简单无需多余配置使用方便,它的缺点是安装包较大。

1、C语言程序环境安装与设置

以下关于c语言学习均使用的是VS2022,它是一个集成开发环境(IDE):一般包括代码编辑器、编译器、调试器和图形用户界面等工具。它的优点是安装简单无需多余配置使用方便,它的缺点是安装包较大。关于环境的安装参考以下教程:https://www.bilibili.com/video/BV11R4y1s7jz/

2、C语言程序结构

它们的名称和具体作用如下:


3、C语言的基本语法

它们的名称和具体作用如下:

关键字 作用
auto 声明自动变量
break 跳出当前循环
case 开关语句分支
char 声明字符型变量或函数返回值类型
const 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue 结束当前循环,开始下一轮循环
default 开关语句中的"其它"分支
do 循环语句的循环体
double 声明双精度浮点型变量或函数返回值类型
else 条件语句否定分支(与 if 连用)
enum 声明枚举类型
extern 声明变量或函数是在其它文件或本文件的其他位置定义
float 声明浮点型变量或函数返回值类型
for 一种循环语句
goto 无条件跳转语句
if 条件语句
int 声明整型变量或函数
long 声明长整型变量或函数返回值类型

register 声明寄存器变量
return 子程序返回语句(可以带参数,也可不带参数)
short 声明短整型变量或函数
signed 声明有符号类型变量或函数
sizeof 计算数据类型或变量长度(即所占字节数)

static 声明静态变量
struct 声明结构体类型
switch 用于开关语句
typedef 用以给数据类型取别名

unsigned 声明无符号类型变量或函数
union 声明共用体类型
void 声明函数无返回值或无参数,声明无类型指针
volatile 说明变量在程序执行中可被隐含地改变
while 循环语句的循环条件


注意事项:

1、注释分为单行注释 // 和多行注释 /*...*/

2、标识符由大小写字母或下划线为起始,后跟大小写字母、下划线0~9的数字, 标识符中的字母分大小写,数字不能作为开头:

以下是有效的标识符书写格式:


mohd                zara                abc                move_name          a_123


myname50        _temp            Mohd            a23b9                     retVal  

4、C语言数据类型





C语言内置数据类型


字符型

名称 书写格式 内存大小 取值范围
字符型 char 1字节 -128到127或0到255
无符号字符型         unsigned char 1字节 0到255

整型

名称 书写格式 内存大小 取值范围
短整型 short 2字节 -32,768到32,767
无符号短整型 unsigned short 2字节 0到65,535
整型 int 4字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
无符号整型 unsigned int 4字节 0 到 65,535 或 0 到 4,294,967,295
长整型 long 4字节 -2,147,483,648 到 2,147,483,647
无符号长整型 unsigned long 4字节 0 到 4,294,967,295
更长整型(C99引入) long long 8字节 -9223372036854775808到9223372036854775807
无符号更长整型 unsigned long long 8字节

0到18446744073709551615

浮点型

名称 书写格式 内存大小 取值范围 精度
单精度浮点型 float 4字节 1.2E-38到3.4E+38 可以精确到小数点后六或七位
双精度浮点型 double 8字节 2.3E-308 到 1.7E+308 可以精确到小数点后十五或十六位
高精度浮点型 long double 8字节 3.4E-4932 到 1.1E+4932 可以精确到小数点后十九或二十位


布尔类型

名称 书写格式 内存大小 取值范围
布尔类型 __bool 4字节 true和flase

整型与浮点型之间的类型转换

整型转浮点数涉及浮点数在内存中的存储方式:

根据国际标准IEEE(电气和电子电工协会)754,任意一个二进制浮点数V可以表示成下面的形式:

V = (-1)^S * M * 2^E

  • (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数
  • M表示有效数字,M大于等于1小于2
  • 2^E表示指数位

V = 5. 0  (十进制)                       V = 5.5  (十进制)


   =101.0  (二进制)                        = 101.1    (二进制)①  


   =1.01 * 2^2                                     =1.011 * 2^2    //与十进制科学计数法类似,这里将10换为2


   =(-1)^0 * 1.01*2^2                          =(-1)^0 * 1.011 * 2^2


即S = 0;M = 1.01;E=2;                即S = 0;M = 1.011;E=2;

①:因为二进制的每一位都有权重,比如11111.11,小数点前面的1就是2^0、2^1、......、2^n

而小数点后面的1每一个代表的就是2^-1、2^-2......、2^-n而相对应的就是0.5、0.25......

IEEE 754规定:

对于32位的浮点数,最高位存储符号位S,接着八位存储指数E,剩下的23位存储有效数字M



对于64位的浮点数,最高位存储符号位S,接着十一位存储指数E,剩下的52位存储有效数字M



浮点数存的过程:

IEEE 754 对有效数字M和指数E,有一些特别规定:

对有效数字M:在计算机内部保存M时, 默认这个数的第⼀位总是1因此可以被舍去,只保存后⾯的小数部分。⽐如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。这样有利于节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字,结果会更精确。


对指数E:⾸先,E为⼀个⽆符号整数,这意味着,E为32位浮点数时的取值范围为0~255;E为4位浮点数时的取值范围为0~2047。(E分别占八个和十一个比特位)但是,科学计数法中的E是可以为负,所以IEEE 754规定,存⼊内存时E的真实值必须再加上⼀个 中间数 ,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。⽐如:2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

我们来分析一段代码来加深理解:

int main()
{
    float a = 5.5;
    return 0;
}

解析:

通过上述的浮点数存的过程我们可以得到这样的解题思路:

float a = 5.5;
//S     E       M
//0 10000001 01100000000000000000000 
//01000000101100000000000000000000
//0100 0000 1011 0000 00000000 00000000
// 4    0     b   0     00        00          //二进制转十六进制表示
//0x40b00000                //最终结果


查看内存窗口:



浮点数取的过程:

E不全为0或不全为1

E= 计算值 + 127 / 1023 、M取小数部分,后面不够的补零

E全为0

E=1-127(或者1-1023)M还原为0.xxxxxx的小数形式

E全为1

如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s)

下面正式开始浮点数与整数之间的类型转换:

# include <stdio.h>
int main ()
{
int n = 9 ;
float *pFloat = ( float *)&n;
printf ( "n 的值为: %d\n" ,n);
printf ( "*pFloat 的值为: %f\n" ,*pFloat);
*pFloat = 9.0 ;
printf ( "num 的值为: %d\n" ,n);
printf ( "*pFloat 的值为: %f\n" ,*pFloat);
return 0 ;
}

分块分析:

//以整数形式存以整数形式取,存的是什么样子读取的就是什么样子
int n = 9;
printf("n的值为:%d\n",n);//结果为9
//以整数形式存以浮点数形式取,直接将整数转换为补码形式对浮点数进行取操作
int n = 9;
0 00000000 000000000000000000001001  9的补码分解成用SME的形式
此时E全为0,则E=1-127,M还原为0.xxxxxx的小数部分
(-1)^0*0.00000000000000000001001 * 2^-126  
1*(一个近似于0的数)
0.000000......    打印结果
printf ( "*pFloat 的值为: %f\n" ,*pFloat);
————————————————
版权声明:本文为CSDN博主「无聊看看天T^T」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_73975164/article/details/133164556
//以浮点数形式存以整数形式取,先进性浮点数存操作将浮点数转换为补码的形式然后输出
*pFloat = 9.0;
1001.0
(-1)^0*1.001*2^3
S = 0;M=1.001;E = 3
0 1000001 000100000000000000000000
printf ( "num 的值为: %d\n" ,n);  结果为1091567616
//以浮点数的形式存以浮点数的形式取,存的是什么样子读取的就是什么样子
*pFloat = 9.0 ;
printf ( "*pFloat 的值为: %f\n" ,*pFloat);  //结果为9.000000

运行结果:



整型与字符型之间的类型转换

简易版:

整型和字符型之间的类型转换涉及ASCII码:

关于ASCII码的具体信息可以通过此链接找到:ASCII码一览表,ASCII码对照表 (biancheng.net)

在这里我们只需要知道ASCII码的以下内容:

一个整数加上字符'\0'就可以得到它对应的字符型

一个字符型减去0就可以得到它对应的整数值

//整型转为字符型
int main()
{
    char a= 65 + '\0';
    printf("a=%c\n", a);
    return 0;
}


 //字符型转为整型
int main()
{
    int a = ‘A’ - 0;
    printf("a=%d\n", a);
    return 0;
}


如果是字符串转整型,那么就可以利用atoi函数

进阶版:

看这样一段代码:

int main()
{
  char a = 5;
  char b = 127;
  char c = a + b;
  printf("%d", c);
  return 0;
}


结果为-124而非132 ,这是因为C语言整型算术运算总是至少以整数类型(int)来进行,表达式中的字符型(char)和短整型(shotr)会在使用时转换为普通整型int / unsigned int,这种转换称之为整型提升

下面是进行整型提升时a和b被分配内存的前后变化:


整型提升的意义在于:可以有效避免因为超出内存分配给它的范围而导致结果被丢弃,同时也增加了结果的精确度。

在进行正式的整型提升之前我们首先得知道原码、反码和补码的概念:

什么是原码、反码和补码?

整数的三种二进制表示方法叫做原码、反码和补码(无符号数没有原反补的概念)

三种方法均有符号位和数值位两部分组成,符号位为0表示负整数,符号位为1表示正整数,其中,符号位为整数二进制表示中的最高位(左边第一个),其余的二进制位都为数值位。

正整数的原码、反码和补码均相同,且符号位固定为1

负整数的原码、反码和补码均不同,且符号位固定为0

对于整型来说数据存放在内存中起始是补码的原因是:使用补码,可以将符号位和数值域统一处理;同时,加法和剑法也可以统一处理(CPU只有加法器)此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路


对于四种码的变换方法遵循下表:(多加了个移码)

原码 反码 补码 移码
真值为正 符号位变为0,其余各位不变 同原码 同原码 符号位变为1,其余各位不变
真值为负 符号位变为1,其余各位不变 符号位变为1,其余各位取反 反码加一 符号位变为0,其余各位取反加一

真值就是5、8、-122这种整数,原码的操作对象就是这些真值的二进制表示。

举一个已知真值求原码的例子:

我们设定[x]原为机器数,x为真值(关于机器数和真值的概念来自计算机组成原理)

①x为+122时,x = + 1111010,[x]原  = 0 1111010

②x为-122时, x = -  1111010,[x]原  = 1 1111010

如何进行整型提升?

有符号整数提升是按照变量的数据类型的符号位来提升的,补码符号位为0则整型提升时高位补零,补码符号位为1则整型提升时高位补1.

⽆符号整数提升,⾼位补0

字符型转整型的整型提升

进行整型提升之前要知道的是,整数在内存中都是以补码的形式操作的

int main()
{
    char a = 5;
//00000000  00000000  00000000  00000101       ---  5的补码
//00000101  -5的补码被截断后的结果赋值给a
    char b = 127;
//00000000  00000000  00000000  01111111         ---  127的补码
//01111111  -   127的补码被截断后赋值给b

截断:char的二进制中只有八个比特位,而5和127是整型二进制位中有三十二个比特位,想要将其存入a中只能截断前面多余的二进制位 ==》一米长的洞塞入四米长的棍子

 char c = a + b;
//00000000  00000000  00000000  00000101      ---- a整型提升后的补码
//00000000  00000000  00000000  01111111        ---- b整型提升后的补码
//00000000  00000000  00000000  10000100       ---- a + b 的补码
//10000100     -  c  (a+b的补码被截断后存储到c中)
printf("%d\n",c);
//打印c的时候还是要进行整型提升,因为%d是按照打印10进制的形式打印有符号的整数
//1111111  11111111  11111111  10000100            ---c整型提升后的结果(补码)
//10000000  00000000  00000000  01111100      ---c的原码
//-124    -打印c的结果
    return 0;
}

字符型与浮点型之间的类型转换

无符号字符型转为整型

int main()
{
    unsigned char a = -1;
//10000000  00000000  00000000  00000001     原码
//11111111  11111111  11111111  11111110            反码
//11111111  11111111  11111111  11111111            补码
//11111111       a截断后
    printf("a=%d\n", a);
//00000000  00000000  00000000  11111111          a整型提升结果(补码)
//00000000  00000000  00000000   11111111         a的原码
//255      打印a的结果
    return 0;
}


字符类型转无符号整型

int main()
{
char a = -1;
//10000000  00000000  00000000  1000000          a的原码
//11111111  11111111  11111111  01111111               a的反码
//11111111  11111111  11111111  01111111               a的补码
//10000000     a截断后
prntf("%u\n",a);
%u打印无符号整数,无符号整数也是整数而a是char a所以仍需要整型提升
//11111111  11111111  11111111  10000000      a整型提升结果(看似是补码但其实不是)
//4294967168  打印a的结果(打印无符号位整数,不需要再求出原码反码直接进行计算将其转换为具体的数即可,这是因为无符号数没原码反码补码的概念)
}


相关文章
|
JavaScript 前端开发 编译器
vue3 源码学习,实现一个 mini-vue(一):搭建框架雏形
vue3 源码学习,实现一个 mini-vue(一):搭建框架雏形
vue3 源码学习,实现一个 mini-vue(一):搭建框架雏形
|
9月前
|
开发者
第十二期乘风伯乐奖--寻找百位乘风者伯乐,邀请新博主入驻即可获奖
乘风伯乐奖,面向阿里云开发者社区已入驻乘风者计划的博主(技术/星级/专家),邀请用户入驻乘风者计划即可获得乘风者定制周边等实物奖励。本期面向阿里云开发者社区寻找100位乘风伯乐,邀请人数月度TOP 1 获奖者(大于108人)可获得AirPods2代!
2865 15
|
9月前
|
算法 Sentinel
【数据结构算法(二)】链表总结
【数据结构算法(二)】链表总结
|
9月前
|
存储 安全 虚拟化
【专栏】虚拟化技术将物理资源转化为虚拟资源,提高资源利用率和系统灵活性。
【4月更文挑战第28天】虚拟化技术将物理资源转化为虚拟资源,提高资源利用率和系统灵活性。通过服务器、存储和网络虚拟化,实现数据中心管理优化、云计算基础构建、企业IT成本降低及科研教育领域创新。尽管面临性能、安全挑战,但技术融合与创新、行业标准制定和可持续发展将推动虚拟化技术未来发展,为各领域带来更多可能性。
274 0
|
9月前
|
开发者
2月更文挑战赛,欢迎热爱技术创作的你!
开发者社区2月更文挑战,欢迎来创作
2486 56
|
存储 弹性计算 网络协议
Open-TDP 多云资源管理系统介绍
Open-TDP 多云资源管理系统介绍
532 1
Open-TDP 多云资源管理系统介绍
|
安全 JavaScript 机器人
阿里云 语音服务-国内语音服务
阿里云 语音服务-国内语音服务
580 0
阿里云 语音服务-国内语音服务
|
9月前
|
IDE Java API
Lombok入门使用教程及其优缺点详解
Lombok入门使用教程及其优缺点详解
119 0
|
机器学习/深度学习 数据采集 缓存
探索Facebook NLP框架Fairseq的强大功能
探索Facebook NLP框架Fairseq的强大功能
|
存储 监控 算法
十大常见排序算法(代码实现、复杂度分析与应用场景)
十大常见排序算法(代码实现、复杂度分析与应用场景)
十大常见排序算法(代码实现、复杂度分析与应用场景)

热门文章

最新文章