在学习C语言基础知识时,对内存的分析很重视,几乎每个知识点都会分析内存存储情况,透过内存的分析也让我们对C语言有了更深的一些了解,C语言跟其他计算机语言相比,对内存的分析和要求更高,下面我们一起来了解和学习一下C语言的内存剖析,是我个人的在学习中的一些总结,如果问题或者不到位的地方也希望大家能够一起交流和指正。
第一讲 进制
进制是一种计数的方式,数值的表示形式,一般我们C语言主要学习的包括十进制、二进制、八进制、十六进制。也就是说,同一个整数,我们至少有4种表示方式。在C语言的程序运行之前,我们都知道先要进行编译和链接,而数据在计算机中的表现形式都是0跟1,编译就是将程序代码转换成计算机能读懂的0跟1的过程。一个int类型数据占据四个字节,32bit,例如0000 0000 0000 0000 0000 0000 0000 1100,变量在内存中的存储细节问题,内存寻址由大到小,变量分配字节也是由大到小,且变量的地址就是其占据的最小的字节地址
1. 二进制
特点:只有0和1,逢2进1
书写格式:0b或者0B开头
使用场合:二进制指令或者二进制文件,变量在内存中就是二进制存储
二进制和十进制的相互转换:举例:0b1100=0*2的0次方+0*2的1次方+1*2的2次方+1*2的3次方,十进制转二进制则是除2
n位二进制位所能表示的数据范围(不考虑负数):0~2的n次方-1
2. 八进制
特点:0~7,逢八进一
书写格式:0开头
八进制和二进制之间的互相转换
3. 十六进制
特点:0~F,逢十六进一
书写格式:0x或者0X开头
十六进制和二进制之间的相互转换
4. 一些常用格式符的总结
%d或%i是以带符号十进制整数的形式输出一个数值
%o以不带符号的八进制形式输出整数
%x以不带符号的十六进制形式输出整数
%c输出一个字符,%s输出一个或者多个字符
%f以小数形式输出单,双精度数,默认输出六位小数,%p输出地址
5. 类型说明符
int 4个字节%d
short 2个字节%d
long 8个字节%ld
long long 8个字节%lld
signed和unsigned的区别:
signed 最高位要当作符号位 有符号,正数,0,负数 其实就等价于int
unsigned 最高位不要当作符号位 无符号,正数,0
第二讲 位运算
之前也学习过很多C语言的基本运算,包括算数运算,赋值运算,自增自减运算,关系运算,逻辑运算还有三目运算等等,而这里的位运算跟数据在计算机内存中的表现形式密不可分,因为数据在计算机中是以0和1的形式存在,而位运算也是基于此形式上进行的运算。
1. 按位与 & :只有对应的两个二进位均为1时,结果位才为1,否则为0
比如9的二进制1001,5的二进制是0101,,9&5=1
规律:二进制中,与1相&就保持原位,与0相&就为0
2. 按位或 | :只要对应的两个二进制位有一个为1时,结果就为1,否则为0
3. 按位异或 ^ :当对应的两个二进制位相异(不相同)时,结果为1,否则就为0
规律:相同数值进行异或,结果肯定是0,比如9^9==0
交换:9^5^6==9^6^5
任何数值跟0进行异或,结果还是原来的数值,9^0==9
可以推出a^b^a==b
关于异或有个跟之前可以联系上的小例子:(省略了#include<stdio.h>和主函数)
1 //不引入第三个变量的情况下交换两个变量的值
2 int a=10;
3 int b=11;
4
5 a=a^b;
6 b=a^b;
7 a=a^b;
8 printf("a=%d,b=%d\n",a,b);//利用异或的特性可以得到a^b^a==b
4. 按位取反 ~ : 二进制0变1,1变0,符号位也会取反
5. 左移 << : 把整数a的各个二进制位全部左移n位,高位丢弃,低位补0,左移n位其实就是乘以2的n次方, a<<n
9<<1 ->9*2的1次方 ==18
9<<2 ->9*2的2次方== 36
9<<n ->9*2的n次方
6. 右移 >> : 把整数a的各个二进制位全部右移n位,保持符号位不变,右移n位其实就是除以2的n次方, a>>n
8>>n ->8除以2的n次方
以上是些关于进制以及位运算的一些知识,可能有些生硬和枯燥,下面我们来看一个位运算的练习题更深入了解一些内存的表现形式:
1 //编写一个函数,用来输出整数在内存中的二进制形式
2 #include<stdio.h>
3
4 void printBinary(int number);// 进行函数的声明
5
6 int main()
7 {
8
9 printBinary(15); // 调用此函数并赋值15
10 return 0;
11
12 }
13
14 void printBinary(int number)
15 {
16 int temp=(sizeof(number)<<3) - 1;//纪录现在挪到第几位,换成sizeof(number) *8-1==31,其实还是
17
18 while (temp >= 0) {
19
20 int value= number>>temp & 1;//右移将每位与上1可以得到此位数
21
22 printf("%d",value);
23 temp --;
24
25 if ((temp+1)%4==0) { // 每四位隔一个空格
26 printf(" ");
27 }
28
29 }
30 printf("\n");
31
32 }
本章学习总结:
本章主要学习的是C语言的进制以及位运算的问题,主要包括进制中的二进制,八进制和十六进制的学习,这些进制之间都是可以相互转换的,同时学习了一些常用的格式符和数据类型的类型说明符,其中需要注意不同的数据类型的输出格式符的不同以及各自不同的类型说明符。本章的第二块讲的是位运算,可能在实际的C语言的编程应用中用到位运算不是很多,但是如果能巧妙的利用位运算的一些规律和特性有时能达到意想不到的效果,比如按位与和按位异或的规律的熟练运用。可能这一章知识点有点枯燥和生硬,但是C语言中对内存的分析是很重要的,学会了分析内存对今后的数组指针等知识的学习很有帮助,因此还是需要好好巩固这一块的基础知识的学习。