常见关键字:
auto表示这个变量是自动的。
后来因为所有的局部变量都是自动变量,所以auto就省略掉了
像char、int、short这种既是类型又是关键字
auto、register、static表示的是一些变量的存储类型,影响变量的存储位置
越往上速度越快,空间就越小,造价越高
数据都是由CPU处理的,数据哪里来呢,早期是从内存里面拿的,处理完再把数据放回内存里面去,如果CPU的处理速度和内存的读写速度比较搭配那还是挺好的,但是随着技术的提升CPU的处理速度越来越快,但是硬件的读写速度没有这么快,这时候就出现问题了,从内存拿个数据,拿了半天才拿到CPU,CPU马上就处理完了,两者效率严重不匹配,这时候就想找一些更快的存储设备,然后CPU直接去寄存器拿数据,当从寄存器拿数据,正在用某一部分的数据的时候,把高速缓存里的数据往寄存器其他位置上挪,把内存中数据往高速缓存上挪,不断把寄存器里的数据进行替换,只要能保证大概率都在寄存器里面把数据都找到,CPU去拿数据都会有,整体的读写速度就提升上来了。从经济成本考虑,又要为了提升计算机整体的处理速度,然后就衍生出来金字塔型的存储结构
既然寄存器的读取速度特别快,那写代码的时候有人就想说把变量,代码啥的全都放到寄存器里面去,这样代码处理速度就快一些。寄存器关键字也只有建议的作用,会不会把变量放进寄存器取决于编译器,编译器会去评估这个变量是不是被大量频繁的使用,如果是可能就会放进寄存器,如果不是可能就不会这样去做,决定权在编译器。当前的编译器很聪明,不用建议它也能帮你判断,然后决定是否放进寄存器
为什么CPU要的数据总是在寄存器就能拿到呢?这是因为不断把它未来即将可能需要的数据从高速缓存往寄存器拿,从内存往高速缓存去拿,只要空间空出来不用了就替换新的数据进去。这里有一个局部性原理:CPU访问 存储器 时,无论是存取指令还是存取数据,所访问的 存储单元 都趋于聚集在一个较小的连续区域中。 时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。
//有兴趣可以看《深入理解计算机系统》
对于typedef是类型重定义,把int*起了个别名int_ptr, int_ptr是一个完整的类型(指针类型)不是替换的,所以用int_ptr定义的c,d都是指针类型的
#define是完成替换的,INT_PTR被替换成int*,int*p1,p2 这样的话只有p1是指针,p1指针指向整形,*给了p1,p2就只能是int类型,要定义应该是int*p1,*p2
static的作用:
1.修饰局部变量(变量的存储位置发生了变化(最本质原因),从而影响变量的生命周期,作用域不受影响)
2.修饰全局变量(static修饰全局变量影响了作用域,本质上修改的是它的链接属性)
3.修饰函数(static修饰函数最终也相当于影响了作用域,本质上修改的是它的链接属性)
1.修饰局部变量:
打印结果是2 2 2 2 2 2 2 2 2 2
static修饰a,出了作用域之后a没有销毁,下次进去的时候a还在,在就不用再创建a了,通过调试可以看到static int a=1没有执行,被跳过去了。static修饰的a还是可以被修改的,只不过不会被重复创建
静态区中的变量是整个程序结束才销毁
static修饰的变量的存储位置发生了变化,从而影响变量的生命周期
最本质的原因是变量的存储位置发生了变化
作用域不受影响,局部变量的a只能在函数内部使用,跟static没关系,加不加static这个a都只能在函数内部使用
2.修饰全局变量:
static修饰全局变量影响了作用域,本质上修改的是它的链接属性
3.修饰函数:
static修饰函数最终也相当于影响了作用域,本质上修改的是它的链接属性
外部函数不声明去调用编译器会警告却可以运行,这是编译器细节处理的问题了,不声明这种写法本身就是存在问题,有的编译器理你,有的就不理你,直接报错了
#define定义常量和宏:
指针:
要谈指针,先理解内存
如果一个内存单元是一个bit,力度太细了,因为在创建变量的时候最小也是个char,如果是这样的话,一个char类型就要分配八个内存单元.
如果一个内存单元是char,就刚刚好一个char类型就给一个地址
每根电线通电
第一根地址线过来的信号是0/1,每根地址线过来的信号也要么是1要么是0
那32根电信号给过来就是32个全0到32个全1之间的范围,列出来32跟地址线上给出来的二进制序列的所有可能性,总共能产生2的32次方个。
每一个这样的二进制序列就可以做一个内存单元的编号
2的32次方个二进制序列作为2的32次方个地址,就能够管理2的32次方个字节的空间
跟代码结合:
10是一个数值要存到a里面去,假设&a取到的是0x0012ff40,这也是个数值(不过是用十六进制表示),这个数值要存起来也得给它一块空间,就给个pa,pa的类型怎么写呢,应该是int*这样写,当我们看到pa前面是int*的时候,我们把pa叫做指针变量。*靠近int还是靠近pa没有明确规定,我们知道pa的类型是int*,理解的时候这个*代表pa是指针变量
指针变量也是变量,所以我们为它也分配了空间
把a地址取出来是有用的,有朝一日能用这个地址找到a所在位置,*pa就是通过这个地址找到a,*pa=20;就是a被覆盖成20。*是解引用操作符
先明白指针变量的作用是存放地址
double是八个字节,但在32位平台下存放你的地址也就需要四个字节而已
sizeof返回值是size_t,想要消除警告可以用%zd接收
结构体:
可以用结构体变量.成员去访问成员,也可以用结构体指针->成员去访问成员