指针
计算机里的数据存放在内存中,所谓的内存,可以理解为一个一个的小格子,类似超市的那种储物柜。里面只能存放 0 和 1,虽然说是计算机只能看懂 0 和 1,其实计算机连 0 和 1 都看不懂,只能知道高低电平,于是人们把低电平抽象为 0,高电平抽象为 1。这也就是所谓计算机只能读懂二进制的原因了。
那么这和指针又有什么关系呢?既然数据存放在内存里(外部存储器另说),那么总有一个能够操纵内存来达到操纵数据的东西吧?这个东西就是指针。
指针,顾名思义,“指向一个地方的针”。其实我个人认为这就已经说明了两件事:
- 指针能够找到它所指向的地方
- 指针自己本身也是占位置的
其实这几条也是最核心的,我们可以把指针理解为 Windows 系统的快捷方式,如果了解快捷方式你应该知道,快捷方式并不是文件本身,甚至连图标都不是,它只是 “指向” 这个文件的文件路径。如果你双击这个快捷方式,它就会找到这个路径然后运行或者打开这个它所指向的文件。
快捷方式可以找到它所指向的地方,然后它本身也是占一定的存储空间的。这不就是指针的概念吗?所以,指针就可以理解为快捷方式。
比如,
int Game = 0;
int *Steam = &Game;
*Steam = 1;
我 int *Steam = &Game ,这个意思就是我找到 Game 这个变量的内存地址然后把这个内存地址原封不动的给到 Steam 这个变量,于是 Steam 变量里存放的就是 Game 变量的地址了,而 int * 则可以认为是“声明一个整形指针变量”。然后如果要操纵 Game 里的数据就使用 *Steam = 1 ,这就是说我把 Game 里的数据已经改成了 1 了,* 符号叫“解引用符”,就理解为双击了快捷方式就行了,双击快捷方式不就是打开这个文件吗,道理是一样的。如果按照上面说的储物柜的例子来说,那这两行代码意思就是说,我打开了一个柜子,然后在里面放了一个 0,并且给它取名叫 Game(int Game = 0 ),然后我把柜子的位置记在一个叫 Steam 小纸条上(int *Steam = &Game; ),然后我按照小纸条上的位置的指引,找到了柜子,并用万能钥匙(*)打开了柜子,把里面的 0 换成了 1(*Steam = 1; )。虽然这个例子也有很多漏洞,但我感觉已经比较具象了。
结构体指针
前面说过,指针存放的是内存地址,其实数组也不过是一连串的数据连续的存放在内存里,但是我们取地址的时候,C 语言只会给我们返回数组的首地址,顺着这个首地址,再根据指针的类型就可往后读取一整串数据了。其实所谓的结构体也一样的,可以理解为升级版的数据,定义一个结构体指针指向这个实例化的结构体,这个指针指向的就是这个结构体对象的第一个数据,剩下的操作也就差不多了。
常见的预编译和条件编译指令:
#define 定义一个预处理宏
#undef 取消宏的定义
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用,判断某个宏是否被定义
内存操作函数
内存操作函数就是一些能操作计算机内存的C语言内置函数 C语言内存分配几种方式:
-
从静态存储区域分配 这种方式主要是系统用于自动分配给全局变量、static变量内存资源的. 它们在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在. -
在栈上分配 这种方式主要是用于系统自动分配给函数内部的局部变量的,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限. -
从堆上分配,亦称动态内存分配. 程序在运行的时候用malloc类或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存.动态内存的生存期由用户决定,使用非常灵活,但问题也最多。
1. 动态分配内存函数
malloc()函数,calloc()函数和free()函数
void *malloc(size_t size);
void free(void *pointer);
void *calloc(size_t num_elements,size_t element_size);
2. 操作内存函数
memset(),函数 memcpy()函数 和 memmove()函数
可以将一段内存空间全部设置为特定的值,所以经常用来初始化字符数组。
void *memset(void *a, int ch, size_t length);
|