C语言:进制转换,内存,指针

进制转换

1. 十进制转换为n进制:

  • 整数部分:短除取余法:
将十进制4563转换为八进制
	4563/8...3
	570/8...2
	71/8...7
	8/8...0
	1/8...1
	0

将十进制数除以要转换的进制数,得数继续除,余数做记录,直到得数为零,取记录的余数的反顺序便是该进制得数;
10723

  • 小数部分:短乘取整法:
将十进制数0.3转换为八进制:
	0.3
	* 8
	2.4(0.4)
	  8
	3.2
	  8
	1.6
	  8
	4.8
	  8
	6.4
	  8
	3.2

显然,该得数在3.2处为死循环,所以取[3.2,3.2)为八进制数部分,即:
0.23146

一般而言,二进制的转换较为漫长,而十六进制的转换较为复杂,所以八进制的存在填补了这个不足,用十进制先过度为八进制,然后再向二,十六进制转换,是常用方法!!

2. n进制转换为十进制:

2047(Q)转换为十进制:
	2047Q
	= 2*8^3 + 0*8^2 + 4*8^1 + 7*8^0
	= 1063

3. 二进制,八进制,十六进制的相互转换:

  1. 二进制转换为八进制和十六进制:
10110101.01101转换为八进制:
	010 110 101 . 011 010
	2	6	5	. 3	  2:265.321011010101.1001101转换为十六进制:
	0010 1101 0101 . 1001 1010
	2	 D	  5	   . 9	  A
	即2D5.9A

以二进制的小数点为中心,分别向左右两侧,逢3(4)位划为一组,不够3(4)位的,以0补足(补零原则:左左右右);再将每一组二进制数转换为与其对应二的八(十六)进制数.

  1. 八进制,十六进制向二进制数转换:
263AD转换为二进制:
	2	  6	  	3	  A	    D
	0010  0110  0011  1010  1101

略…

内存

1. 内存基本概念:

  1. 计算机表达信息的最小物理单位: 位(二进制单位)比特(bit)
  • 字节:1B= 8b
  • 1KB = 1024B = 2^10B
  • 1MB = 1024KB = 2^20B
  • 1GB = 1024MB = 2^30B
  • 1TB = 1024GB = 2^40B
  • 1PB = 1024TB = 2^50B
  1. 内存
  • 内存是由多个字节组成的一堆,线性,连续的存储空间;
  • 字节是内(外)存分配存储空间的基本单位;
  • 对内存中的众多字节,计算机系统是通过对字节进行唯一性编号来管理的,编号与字节之间是一一对应关系;
  • 一个计算机系统能够管理的内存大小,取决于参与内存中的字节编号的二进制位数;
  • 对字节的编号,有三个原则:
    (1). 从零开始;
    (2). 连续编号;
    (3). 二进制编号;
  • DOS系统采用20位二进制对每一个字节进行编号;即能够管理的内存空间(字节数)为2^20B = 1MB;
  • 80386/486采用3个字节对每一个字节进行编号(即采用3*8=24位二进制对每一个字节进行编号);能够管理的内存空间(字节数)为2^24B = 16MB;
  • 奔腾计算机的地址总线有32根(即编址空间为4B),能够访问的空间为2^32B = 4GB
    在这里插入图片描述

M: 内存;

Data Bus: 数据总线,即数据通信信道,用来在CPU与内存之间传送数据,是双向的;

Address Bus: 地址总线,用来对内存中的每一个字节编号,该总线不在内存中!!

2. 软件运行过程与内存管理:

  1. 操作系统是计算机资源的管理者,即包括内存在内的所有计算机软硬件设备,都是在OS(操作系统)的统一管理下运行的;
  2. 软件运行前,需先向操作系统申请存储空间;再有足够空间的情况下,OS将分配给该软件一段内存空间供该软件运行;
  3. 软件分配得到的内存空间,在其运行过程中不在被OS分配给其他软件运行;
  4. 软件运行完毕后,将提请OS收回其所占用的内存空间,以便再次分配给其他软件使用(这意味着内存是重复使用方式);
  5. 由上述可知,一个软件运行所被分配到的内存空间,其内存基本上不可能是一无所有的,而是存在着曾经使用过这段空间的软件的残留数据,即垃圾数据;

3. 内存映像图:

在这里插入图片描述

理解:

  • 在32位系统中,每一个字节由32位的二进制存储,即32个0/1,但是人们为了方便表示,便引入了十六进制的表示方法,而四个位的二进制为一位的十六进制,所以32位的二进制便简化成了32/4 = 8位的十六进制表示,一位十六进制表示四位二进制,而八位的二进制等于一个字节大小,所以两位的十六进制占一个字节大小,所以八位十六进制占四个字节大小;
  • 结论:32位的二进制 = 8位的十六进制 = 4个字节!!!

指针

理解:

  • 当我们存储一些数据时,这些数据随机的在内存中获得一串地址,例如:
    short 12901;这个数据是short类,占两个字节大小,在32位系统中就需要八个字节来存储它(给它的编号),如上图3A 2B 65 32//3A 2B 65 33,开头的四个字节称为首地址;
  • 而当我们需要把这个数据从内存中读取出来时,就需要这个数据的首地址了,可是首地址又保存在哪里呢;
  • 这时便引入了指针,该首地址也保存在内存中,且显然该首地址占用了四个字节(3A 2B 65 32),指针在内存中的地址(编号)也需要保存,所以指针也有指针!!!( * )
  • 而指针所指向的空间只是声明了该空间的首地址,完全不清楚该空间所保存的数据的类型这时便引入了指类,即在指针前声明该指针所指空间的数据类型:( int * );指针的指针的数据类型和指针的数据类型一致

1. 指针的两个要素:

  • 首地址: 内存中多个(连续)字节中的第一字节编号;

32位系统下每个字节的编号都是32位二进制(即,4B),任何类型的指针都只占用4B存储空间;

  • 指类: 指针所指向的空间数据类型;

short ** b; b变量本身的类型是: short **
其指类是: short *
将指针定义中的最后一个*去掉,剩余部分就是该指针变量的"指类".

2. 指针的基本运算(& 和 *):

  • & : 取地址运算符:(即,获得某数据的首地址)
  1. 单目运算符,优先级在单目运算符中比较低,低于++ , - -;

  2. 语法 —> 左值: “&常量” 和 "&表达式"是语法错误.

  3. &&n //错误! &&是逻辑与运算符

  4. &(&n) // 错误! ()表达的是表达式或者函数调用

short i, j, *p, *q, **r;
两个值类变量: i 和 j; 三个指针类变量: p, q, r;
p 是指针变量,其指类是 short;
q 的指类是short; r 的指类是short *;
eg : r = &j 是错误的,因为 = 两侧的指类不同,r 的指类是 short * ;而 &j 的指类是 short 类 即: 指针的指类不同, 不能相互运算!

5. 指针类 (常量, 变量, 表达式) 的相互运算, 必须保证指类相同!

int i, j, *p, *q, **r;
p = &i ; // 取出 i 空间的首地址, 赋值给p空间 . 这称为"p 指向 i"
q = &j ; // q 指向 j
r = &p ; // r 指向 p

  • *: 运算符:
  1. 单目运算符, 且与&优先级相同,且与&互为逆运算(连续两个&和 * 运算在一起,相互抵消) eg: *&n < = > n;

  2. 语法:

short i, j, *p, *q, **r;
p = &i
q = &j
r = &p

  • p = 30; //将30赋值给"p所指向的空间".i = 30;
  • q = * p + 15; // 将p所指向的空间的值,与十五求和,将和赋值给q所指向的空间;
  1. *某的念法:
    a .其作为左值,应念成“某所指向的空间”;
    b .其在表达式中,应念成:“某所指向的空间值”。

  2. 若说 “α 指向 β”,就意味着:
    a. α 的值,就是β 空间(变量)的首地址(反之亦然)。
    b. α 至少是指针类,且其指类一定是β的类型。

  3. 定义语句中的 * ,不是“指向运算符”,它只是“指针身份”的声明。

char i,j,*p ;


double *p;
*p = 3.14;

  • 上述语句会引起所谓的“运行时致命错误”。
  • 变量p定义为指针变量,占用4B,但是没有赋初值,其为垃圾数据(其数值不可预料);
  • *p = 3.14应念作:将3.14赋值给p所指向的空间,即将3.14赋值给“以p作为首地址,该首地址所指向的空间”
  • 总的来说:将3.14赋值给以垃圾值为首地址,所指向的空间!可是这个空间在哪里?没人知道!
  • 这个垃圾值的取值范围在0到40亿之间,若落在当前软件所申请的空间范围内,则相安无事,反之,这个操作(*p = 3.14)将对不属于本软件所申请的空间进行操作,会被操作系统认为是“非法访问”,操作系统将强行终止这个软件的执行!
    在这里插入图片描述
	*r = q;
	//将q的值赋值给r所指向的空间,而r指向的空间为p的首地址,所以p空间的内容被修改为&j;
	*r = &j;
	//将j空间的首地址赋值给r所指向的空间;等同于*r = q;
	p = q;
	//同上;

3. 指针的其他运算:

  1. p + / - int => p’
  • 指针加(减)整型值,其结果是一个指针,且指类不变。
  • p + 1 所得到的指针 p‘ 将指向 p 所指向的空间的下一个指类元素空间;

short a[10], *p, *q = &a[7];
// 将a[7]的首地址赋值给q(这里q是定义语句中的,所以只是指针类的声明)
p = &a[0];
// 将 a[0] 赋值给p所指向的空间;

  • 指针 + 1所得到的 “字节编号” 的值,与指针原值(原字节编号)相差sizeof(指类)
  • 指针 + n 的值与指针原值相差 n 倍的sizeof(指类)。
void main(void)
{
	char str[80] = "abcdefghijk", *p;
	int *q;

	p = &str[3]; //把str[3]的首地址赋值给p;
	q = (int *)p; //想要把p的值赋值给q,但p为char类型,q为int类型,所以需要强转,规则为“以左边类型为基准”。现在q, p都指向d
	++q; //把q所指向的位置向后加一位,而q的指类为int,占四个字节,所以向后加四位
	p = (char *)q; 
  1. p - p’ = > int
  • 指针减指针,其结果的绝对值是:两指针所指向的空间之间的指类元素个数。
    在是撒旦这里插入图片描述

如图,p,q都是int类型,q* - p* 为 18 - 10 = 8;但是这两个数据的类型为int,一个int类型的数据占4个字节,所以q,p间的数据个数为8 / 4 = 2个,即 q* - p* = 2;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值