C语言中进制转换与函数
进制转换:
为什么使用二进制、八进制、十六进制?
由于现在的CPU只能识别高低两种电平,只能使用二进制数据进行计算
二进制虽然能够被计算机直接计算,但是不方便书写、记录,因此将数据以八进制方式为了更方便记录在文件中
随着CPU位数不断增加,八进制不能满足需求,所以发展出了十六进制来表示数据,
由于历史原因八进制还不能退出历史舞台
十进制转二进制:(十进制转其他进制)
求余法: 用2对数据求余,然后再继续对商求余,知道商为0结束,过程中产生的余数就是该数据的二进制(逆序)
n %2 余数
商%2
...
127 %2 1
63 %2 1
31 %2 1
15 %2 1
7 %2 1
3 %2 1
1 %2 1
0 0
二进制:01111111
求权法: 数据- 2^(n-1) 如果可以减,则第n位为1,否则为0
137
128 64 32 16 8 4 2 1
1 0 0 0 1 0 0 1
手算: 79 28 63 119
10 A 11 B
二进制转十进制:(其他进制转十进制)
二进制数据每位 乘2^(n-1) 结果求和
10011101 128+16+8+4+1 157
二进制转八进制:
三个二进制位转为一位八进制位
二进制 10 011 001 101 110
八进制 2 3 1 5 6
二进制转十六进制:
四个二进制位转为一位十六进制位
二进制 10 0110 0110 1110
十六进制: 2 6 6 E
在C代码中,以0开头的数据是八进制数据,以0x开头的是十六进制数据
%o 以八进制形式显示数据
%x 以十六进制显示数据
%#o %#x 以对应的进制显示数据
原码、反码、补码:
原码: 数据的二进制
反码:
正数的原码就是它的反码
负数的反码是它的原码符号位不变,其它位按位求反
补码: 数据在内存中是以补码形式存储的
正数的原码就是它的补码
负数的补码是它的反码+1
负数的补码:
1、数据转换为二进制
2、二进制符号位不变,其余按位求反得到反码
3、反码+1得到补码
-127
1111 1111
1000 0000
1000 0001 补码
0000000000000000000000001000 0001 %d --127->129
补码转数据:
无符号的补码直接转成十进制数据
有符号看最高位是0,说明是正数,也直接转成十进制数据
有符号且最高位是1,说明是负数
1、补码-1得到反码
2、反码符号位不变,按位求反得到原码
3、原码转换成十进制
11111111 补码
11111110 反码
10000001 原码 -1
最大值+1 = 最小值
最小值-1 = 最大值
位运算符:& | ~ ^ << >>
A & B 按位相与
01101010 0x6A
01110110 0x76
01100010 0x62
A | B 按位相或
01101010 0x6A
01110110 0x76
01111110 0x7E
~A 按位求反
01101010 0x6A
10010101 0x95
A^B 按位异或 相同为0,相异为1
01101010 0x6A
01110110 0x76
00011100 0x1C
A<<n 把A的补码向左移动n位,左边丢弃,右边补0
01101010 0x6A << 4
10100000 0xA0
A>>n 把A的补码向右移动n位,右边丢弃,左边补符号位
11101010 0xEA >> 3
11111101 0xFD
4位先与0 ,再或1010
printf("%d\n",n & ~(0xf<<4) | (0xA << 4));
00000000 00001111
00000000 11110000
11111111 00001111
xxxxxxxx 0000xxxx
0xA << 4
00000000 10100000
xxxxxxxx 1010xxxx
函数:
是一段具有某项功能的代码,是C语言中管理代码的最小单位
把代码封装成一个个的函数,可以方便管理和调用代码
函数的分类:
标准库函数
C语言标准委员会为C语言以函数形式提供一些基础的功能,被封装在libc.so库,默认添加的,所以使用时需要包含头文件,以函数名(参数) 来调用函数
int isalnum(int c);
int isalpha(int c);
int isdigit(int c);
int islower(int c);
int isupper(int c);
int isxdigit(int c);
int toupper(int c);
int tolower(int c);
int abs(int j);
以下函数被封装在libm.so 数学库中,使用时需要在编译时加参数-lm
double sqrt(double x);
double pow(double x, double y);
double ceil(double x);
double floor(double x);
double fabs(double x);
time_t time(time_t *t);
功能:返回自1970-1-1 0:0:0 到运行时过了多少秒
int system(const char *command);
功能:调用系统命令 system("clear");
int rand(void);
功能:返回一个随机数
void srand(unsigned int seed);
功能:种随机种子,设置取随机数的位置
练习3:获取10个[100,1000]范围内的随机数
num = rand()%901+100
[a,b) rand()%(b-a)+a
练习4:随机出一注双色球中奖号码
红球6个:1-33,不能重复 rand()%33+1
蓝球1个:1-16 rand()%16+1
系统函数
系统函数不是函数,只是操作系统以函数接口的形式提供的一些功能
内存管理、信号处理、文件IO、文件管理、进程管理、进程通信、线程管理、线程同步、网络通信
第三方库函数
由第三方提供的收费、开源的库函数
github
MD5
XML
JSON
自定义函数:
为了更方便地管理代码、减少冗余把代码封装成函数
注意:一个函数尽量控制在50行左右,一个函数一个功能
函数声明:函数声明目的是为了告诉其他代码该函数的调用格式
返回值类型 函数名(类型1 变量名1,类型2 变量名2...);
1、C语言中函数名一般全部小写,用下划线分隔
2、如果不需要参数建议写void,不要空着
3、如果不需要返回值写void
4、如果在调用前有函数的定义,那么函数声明可以省略
隐式声明:
当调用函数时没有函数声明或定义,编译器会猜测函数的格式,参数列表会根据调用时的提供数据来猜测,返回值猜测为int类型
如何避免:在调用前,提供函数的声明或定义
函数定义:
返回值类型 函数名(类型1 变量名1,类型2 变量名2...)
{
函数体;
return val;
}
注意:return语句的作用:1、返回值给调用者 2、结束函数的执行
函数调用:
函数名(实参);
返回值会放在调用的位置,可以用变量记录下来,也可以直接显示,如果不记录就会丢失
函数传参:
1、实参与形参之间是以赋值的形式传递数据的(单向值传递)
2、在函数内定义的参数,只属于它所在的函数,出了该函数就不能在使用了
3、return语句其实是把数据放置到一个公共区域(函数和调用者共用),如果不写return语句,调用者从该区域中获取的是一个随机的垃圾数据
4、当数组作为函数的参数时,长度会丢失,需要额外多加长度的参数来把长度传递过去
5、数组的传递是"址传递",函数和函数的调用者可以共享数组
练习5:实现一个函数,找出数组中的最大值
练习6:实现一个函数,对数组进行排序
练习7:实现一个函数,查找数组中是否存在某个值,如果存在则返回该数据在数组中的下标
int find_arr(int arr[],int len,int val);
设计函数的准则:
1、一个函数最好只解决一个问题,从而可以降低出错率
2、最好不要过分依赖其他函数,降低耦合度
3、数据由调用者提供,结果返回给调用者,以此提高函数的通用性
4、对于调用者提供的非法参数,可以通过返回值、注释等方式来告诉调用者数据非法,以此提高函数的健壮性
5、一个函数最多不要超过50行
进程映像:
程序:储存在磁盘中的可执行的文件(二进制文件、脚本文件)
进程:在系统中运行的程序
进程映像:进程的内存的分布情况
text 代码段: 存储的是二进制的指令、常量数据,权限是只读的,如果强行修改会产生段错误
data 数据段: 存储的是初始化过的全局变量、被初始化过的静态局部变量
bss 静态数据段:存储的是未初始化过的全局变量、未初始化过的静态局部变量,程序运行前会清零
stack 栈: 局部变量、块变量,会随着进程运行而申请、释放,由系统管理的,缺点:小
heap 堆: 由程序员手动管理的,手动申请、释放的,使用比较麻烦,特点是:足够大,理论上无限大
局部变量和全局变量:
全局变量: 定义在函数外的
存储位置: data(初始化过的)或者bss(未初始化过的)
生命周期: main函数运行开始前到程序结束才释放
作用范围: 程序中的任何位置
局部变量: 定义在函数内的
存储位置: stack栈内存
生命周期: 函数的定义语句开始,直到函数执行结束
作用范围:只能在本函数内使用
块变量: 定义在if\for\while等语句块内的变量
存储位置: stack栈内存
生命周期: 函数的定义语句开始,直到函数执行结束
作用范围:只能在语句块内使用
注意:局部变量和全局变量可以同名,但是会屏蔽同名的全局变量,同名块变量会屏蔽同名的局部变量和全局变量
建议:全局变量首字母大写
类型限定符:
auto
用于定义自动申请、自动释放的变量(局部变量),不加代表了加
不能用于修饰全局变量
const
显示地"保护"变量不被修改
但是,如果要强制修改还是可以修改的
如果对初始化过的全局变量,用const修饰后,存储位置从data变成了text
extern
声明外部的全局变量,声明的变量已在别处定义过,请放心使用
但是只能临时通过编译,如果没有定义,链接时依然会报错
只是声明变量,不能赋值
static
被static修饰过的变量称为静态局部变量,局部全局变量
改变存储位置:
改变局部变量的存储位置,由stack改data或者bss(由是否初始化决定)
延长生命周期:
延长局部变量的生命周期
限制作用范围:
限制全局变量、函数只能在本文件内使用
可以防止函数、全局变量重名、防止被别人调用
存储介质:
硬盘->内存->高速缓存->寄存器->CPU
register
申请把变量的存储介质由内存转移到寄存器存储,如果能成功,数据的读取速度会大幅提升,寄存器数量有限,申请可能失败
volatile
编译器的取值优化:
变量的值没有发生改变时,后续的取值会进行优化,不再去内存中读取,而是使用第一次读取的结果,可以节约时间
使用volatile修饰的变量不做取值优化
volatile int num = 10;
if(num == num)
{
//可能为假
}
一般硬件编程和驱动编程时使用
typedef
类型重定义,注意不是替换关系,定义变量时如果前面加上typedef,则变量名就变成了类型
typedef int num;
#define num int;
num num2;
uint8_t size_t time_t
typedef unsigned char uint8_t
函数递归:
分治:分而治之 循环、递归
函数自己调用自己的行为叫做递归,会产生死循环
递归可以实现分治算法,其实就是把一个大而复杂的问题,分解成若干个相同的小问题,解决小问题,直到全部问题解决
1、出口
2、分解成一个小问题
3、自己调用自己
斐波那契数列
1 0|1 1 2 3 5 8 13 21 ...
练习1:求前N项斐波那契数列
5
递归函数好处是容易理解,思路清晰
递归函数每次调用都会在栈内存产生一份自己的内存拷贝,直到到达出口,才会一层层地返回,因此递归非常地耗费内存资源,与循环相比,速度非常慢
递归的优缺点:
1、耗费内存、速度慢
2、好理解、思路清晰
3、能使用循环就用循环
C语言中进制转换与函数相关推荐
- python进制转换函数-Python中进制转换函数的使用
Python中进制转换函数的使用 关于Python中几个进制转换的函数使用方法,做一个简单的使用方法的介绍,我们常用的进制转换函数常用的就是int()(其他进制转换到十进制).bin()(十进制转换到 ...
- c语言中10转8和16的转换,(C语言)10进制转换2,8,16进制
(C语言)10进制转换2,8,16进制 作者:vinseven #include"stdio.h" #include"conio.h" #include&quo ...
- python进制转换#replace函数删除多余符号
首先是在python中,将十进制转换为不同进制: print(bin(37)) #bin(n)是将十进制整数n转换为二进制 print(oct(37)) #oct(n)是将十进制整数n转换为八进制 p ...
- 【ZZULIOJ】1112: 进制转换(函数专题)
ZZULIOJ题解 1112: 进制转换(函数专题) 题目描述 输入一个十进制整数n,输出对应的二进制整数.常用的转换方法为"除2取余,倒序排列".将一个十进制数除以2,得到余数和 ...
- 1112: 进制转换(函数专题)
1112: 进制转换(函数专题) 时间限制: 1 Sec 内存限制: 128 MB 提交: 3448 解决: 2599 [提交] [状态] [讨论版] [命题人:admin] 题目描述 输入一个十进制 ...
- ZZULIOJ 1112: 进制转换(函数专题)
进制转换(函数专题) 题目描述 输入一个十进制整数n,输出对应的二进制整数.常用的转换方法为"除2取余,倒序排列".将一个十进制数除以2,得到余数和商,将得到的商再除以2,依次类推 ...
- python中进制转换关系
python中进制转换关系 标题整数之间的进制转换: hex(16) # 10进制转16进制 print(hex(16) ) >>'0x10' oct(8) # 10进制转8进制 prin ...
- 从0开始学习C语言————数组、进制转换、函数
数组: 什么是数组: 变量的组合,是一种批量定义变量的方式 定义: 类型 数组名[数量]; int num1,num2,num3,num4,num5; int arr[5]; 使用:数组名[下标]; ...
- C语言笔记-进制转换
一.进制转换 为什么要使用二进制.八进制.十进制.十六进制 因为现在的CPU只能识别高低电平,只能对二进制数据进行计算 虽然二进制的数据可以直接被CPU识别计算 ...
- 进制转换和函数的定义
进制转换: 为什么使用二进制.八进制.十六进制 因为现在的CPU只能识别高低两种电流,只能对二进制数据进行计算. 二进制数据虽然可以直接被CPU计算识别,但是不方便书写.记录,把二进制数据 ...
最新文章
- 封装了一套WeCenter的IOS SDK
- ros安装orocos造成工作空间编译不通过
- Chapter 17 高级进程间通信
- angularjs 中的$digest和$apply区别
- 单片机指令周期、机器周期、状态周期、时钟周期
- android studio安装教程博客园独王,Android Studio安装与配置
- wpf 如何设置弹出窗口必须关闭才能打开其他软件_Mac忘记登录密码?以防万一,必须收藏。...
- C语言试题八十八之实现选冒泡排序算法
- 递归-计算字符串长度(代码、分析、汇编)
- 一道简单的编程题,不过您做对了吗?
- SQL Server:专业的DateTime范围
- 阿里云云原生一体化数仓入选 2022数博会“十佳大数据案例”
- 中兴软件测试过往面试题汇总
- java聊天室设计_JAVA网络聊天室的设计与实现
- One More Check: Making “Fake Background” Be Tracked Again
- VueSSR的一些理解和详细配置
- C++ SLT之map的用法总结
- devise 自定义手机号登录
- Android接收和发送短信
- UVM—virtual sequencer and virtual sequence详解
热门文章
- python网站上搜索答案_用python搭建百万赢家自动搜索答案
- system.gc()和system.runFinalization()区别作用
- 计算机与信息技术研究生,计算机与信息技术学院研究生必读经典文献.doc
- mysql 建表结构_MySQL学习系列之二——创建表及对表结构的基本操作
- C/C++遍历目录下的所有文件(Windows篇)
- centos8终端fish安装
- java君临天下单机游戏_君临天下java单机游戏
- 开源游戏java引擎_基于Java的开源3D游戏引擎jMonkeyEngine
- 【数据挖掘】基于密度的聚类方法 - OPTICS 方法 ( 算法流程 | 算法示例 )
- 谈谈可视化编程 (转)