lijifeng

导航

黑马程序员——C语言基础 内存剖析

                                 (以下内容是对黑马苹果入学视频的个人知识点总结)

 (一)进制

 进制是一种计数的方式,数值的表示形式。有多种进制十进制、二进制、八进制、十六进制。也就是说,同一个整数,我们至少有4种表示方式。

1>二进制

①特点只有0和1,逢2进1

②以0b开头

③一般是二进制文件\指令,变量再内存中存储、

④可以与十进制相互转换

⑤数据范围为0-2的n次方-1

2>八进制

①0--7,逢8进1

②以0开头

③可以很快和二进制转换

3>十六进制

①0--F,逢16进1

②以0x或者大写的0X开头

③可以很好和二进制相互转换

 

以上是不同进制的输出占位符

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     // 默认情况下,就是十进制
 6     int number = 12;
 7     
 8     // 二进制(0b或者0B开头)
 9     int number2 = 0B1100;
10     
11     // 八进制(0开头)
12     int number3 = 014;
13     
14     // 十六进制(0x或者0X开头)
15     int number4 = 0xc;
16     
17     // %d以10进制整数的形式输出一个数值
18     printf("%x\n", number);
19     
20     return 0;
21 }

 

(二)变量的内存分析

1>内存以字节为单位,不同的类型占用不同的字节

2>变量的存储

①不仅和类型有关,也和编译器环境有关

②内存由大到小寻址

③只存储二进制形式

④每个变量都有地址:第一个字节的地址就是变量的地址

⑤查看内存地址的两种方式:%x和%p

 查看整数的二进制形式

 1 #include <stdio.h>
 2 
 3 
 4 /*
 5  1.二进制转十进制
 6  0b1100 = 0 * 2的0次方 + 0 * 2的1次方 + 1 * 2的2次方+ 1 * 2的3次方
 7         = 0 + 0 + 4 + 8 = 12
 8  0b1111 = 1 + 2 + 4 + 8 = 15
 9  0b1010 = 10
10  
11  2.十进制转二进制
12  67 = 64 + 2 + 1 = 2的6次方 + 2的1次方 + 2的0次方
13     = 0b1000000 + 0b10 + 0b1
14   = 0b1000011
15  
16  3.n位二进制的取值范围
17  2位二进制位的取值范围:0~3  0~2的2次方-1
18  3位二进制位的取值范围:0~7  0~2的3次方-1
19  n位二进制位的取值范围:0~2的n次方-1
20  
21  
22  4个字节 -> 31bit
23  0    000 0000 0000 0000 0000 0000 0000 1100
24  0 ~ 2的31次方-1
25  */
26 
27 int main()
28 {
29     void putBinary(int);
30     
31     putBinary(-12);
32     
33     putBinary(13);
34 
35     return 0;
36 }
37 
38 // 输出一个整数的二进制存储形式
39 void putBinary(int n)
40 {
41     int bits = sizeof(n) * 8;
42     while (bits-->0) {
43         printf("%d", n>>bits&1);
44         if (bits%4==0) printf(" ");
45     }
46     printf("\n");
47 }

3>负数的存储

① 一个字节的取值范围是,负数的表示形式一般以补码存储

不同类型的取值范围

(三)类型说明符

 1>short和long

①short和long可以提供不同长度的整型数,也就是可以改变整型数的取值范围。

②如果使用的整数不是很大的话,可以使用short代替int,这样的话,更节省内存开销。

③short跟int至少为16位(2字节)但是long至少为32位(4字节),short的长度不能大于int,int的长度不能大于long,char一定为为8位(1字节),毕竟char是我们编程能用的最小数据类型

④long可以连续用两个在32位环境下一个long占4个字节,两个占8个。64位都占8个字节

2>signed和unsigned

它们的主要区别就是最高位是否要当做符号位,并不会像short和long那样改变数据的长度,即所占的字节数。

①表示有符号,也就是说最高位要当做符号位,所以包括正数、负数和0。其实int的最高位本来就是符号位,已经包括了正负数和0了,因此signed和int是一样的,signed等价于signed int,也等价于int。signed的取值范围是-231 ~ 231 - 1

②表示无符号,也就是说最高位并不当做符号位,所 以不包括负数。在64bit编译器环境下面,int占用4个字节(32bit),因此unsigned的取值范围是:0000 0000 0000 0000 0000 0000 0000 0000 ~ 1111 1111 1111 1111 1111 1111 1111 1111,也就是0 ~ 232 - 1

(四)位运算

1) & 按位与

1>功能是只有对应的两个二进位均为1时,结果位才为1,否则为0。

2> 二进制中,与1相&就保持原位,与0相&就为0

2) | 按位或

1>只要对应的二个二进位有一个为1时,结果位就为1,否则为0。

3)  ^ 按位异或

1>当对应的二进位相异(不相同)时,结果为1,否则为0。

2>规律:

①相同整数相^的结果是0。比如5^5=0

②多个整数相^的结果跟顺序无关。比如5^6^7=5^7^6

③因此得出结论:a^b^a = b

4) ~ 取反

对整数a的各二进位进行取反,符号位也取反(0变1,1变0)

5)  << 左移

把整数a的各二进位全部左移n位,高位丢弃,低位补0。左移n位其实就是乘以2的n次方。由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性

6)>> 右移

①把整数a的各二进位全部右移n位,保持符号位不变。右移n位其实就是除以2的n次方

②为正数时, 符号位为0,最高位补0

③为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定

#include <stdio.h>


int main()
{
    /* 按位与 &
     
     10101010000
     00000100000
     -------------
     00000000000
     
     10111011
     10101101
     ---------
     10101001
     
     1001
     0101
     -----
     0001
     */
    
    /*
     按位或 |
     1001
     0101
     -----
     1101
     */
    
    
    /*
     按位异或 ^ 
     1.相同数值进行异或,结果肯定是0,比如9^9
     2.交换 9^5^6 == 9^6^5
     3.任何数值跟0进行异或,结果还是原来的数值,9^0 == 9
     4.a^b^a == a^a^b == 0^b == b
     
     1001
     0101
     -----
     1100
     
     1001
     1001
     -----
     00000
     
     0101
     0000
     ----
     0101
     
     9^5^9 == 9^9^5 = 0^5 = 5
     
     a^b^a == b
     */
    //printf("%d\n", 9^9);
    
    //printf("%d\n", 9 ^ 5);
    
    /*
     按位取反 ~
     ~0000 0000 0000 0000 0000 0000 0000 1001
      1111 1111 1111 1111 1111 1111 1111 0110
     */
    //printf("%d\n", ~9);
    
    /*
     左移 <<
     
     0000 0000 0000 0000 0000 0000 0000 0000
     00 0000 0000 0000 0000 0000 0000 100100
     
     9<<1 -> 9 * 2的1次方 == 18
     9<<2 -> 9 * 2的2次方 ==36
     9<<n -> 9 * 2的n次方
     */
    
    //printf("%d\n", 9<<1);
    
    /*
     右移 >>
     0000 0000 0000 0000 0000 0000 0000 0000
     000000 0000 0000 0000 0000 0000 0000 10
     111111 1111 1111 1111 1111 1111 1111 10 
     
     8>>1 -> 8/2 == 4
     8>>2 -> 8/2的2次方 == 2
     8>>n -> 8/2的n次方
     */
    
    printf("%d\n", 8>>3);
    
    return 0;
}

 

posted on 2015-03-23 18:23  lijifeng  阅读(194)  评论(0编辑  收藏  举报