(内容为学习笔记,如有错误,还望指正,如有遗漏,还望补充)
1.内存分配
1)内存分区(变量可能被分配的内存分区)
栈:函数中的参数和局部变量存储在栈上
堆:程序中一块预留的内存空间,可由程序自由使用,堆中被程序申请使用的内存在被主动释放前将一直有效
静态:全局变量和静态局部变量
2)堆空间内存的申请和释放
a.头文件:
#include<stdlib.h>
b.申请内存
void *malloc(size_t size);
//申请后的结果是void地址,赋值给指针变量
//malloc前的(int *)表示将malloc申请的void类型地址强制转换位int类型地址
//10*sizeof(int)表示申请的地址大小是10个int类型地址大小,即40个字节
//这样申请出来的地址就可以当作数组来用,如p[0],p[1]..
int* p = (int *)malloc(10*sizeof(int));
c.释放内存
void free(void *p);
p = NULL;
//free只是释放了指针p指向位置内存上的数据,并没有改变指针p的指向
//如果在此调用可能会发生错误
//free释放指针后应该将指针置空
3)注意事项
a.malloc 和 free 成对去写。(malloc 申请的空间,使用结束后,要及时的free )malloc不free会造成 内存泄漏。
b. malloc 申请内存,会成功或失败,如果成功,则可以使用申请来的堆空间。 如果失败,会返回 NULL(NULL就是0 空指针。内存不够就会失败)。
c. 在堆内存被释放掉之后,及时将指针 p 归零,以防出现使用这块已经被释放掉的内存,造成不必要的风险(野指针)。
2.位运算
1)左移右移
<< //左移
>> //右移
左移示例
#include <stdio.h>
int main()
{
char a = 1; //二进制0000 0001
a = a<<1; //左移1位,0000 0010
printf("%d\n", a); //输出2
a = a<<2; //再左移2位,0000 1000
printf("%d\n", a); //输出8
return 0;
}
右移示例
#include <stdio.h>
int main()
{
unsigned char a = 8; //二进制位0000 1000
a = a>>1; //右移1位,0000 0100
printf("%d\n", a); //输出4
a = a>>2; //右移2位,0000 0001
printf("%d\n", a); //1
return 0;
}
2)按位取反
~
将变量中所有的位,1变成0,0变成1
#include<stdio.h>
int main()
{
unsigned char a = 0x0f; //十六进制0f 二进制0000 1111
printf("%x\n",a); //输出f
a = ~a; //取反为0xf0 二进制1111 0000
printf("%x\n",a); //输出f0
return 0;
}
3)按位与
&
双目运算 对应的位,有一个为0结果就是0
#include <stdio.h>
int main()
{
unsigned char a = 0xA5; //二进制1010 0101
unsigned char b = 0x8C; //二进制1000 1100
unsigned char c = a&b; //有0得0
printf("%#x\n", c); //输出0x84,二进制1000 0100
return 0;
}
4)按位或
|
双目运算 对应的位,有一个为0结果就是0
指定的二进制位,写1
#include <stdio.h>
int main()
{
unsigned char a = 0xA5; //二进制1010 0101
unsigned char b = 0x8C; //二进制1000 1100
unsigned char c = a|b; //有1得1
printf("%#x\n", c); //输出0xAD,二进制1010 1101
return 0;
}
5)按位异或
^
指定位取反 对应的位,相同得0,不同得1
#include <stdio.h>
int main()
{
unsigned char a = 0xA5; //二进制1010 0101
unsigned char b = 0x8C; //二进制1000 1100
unsigned char c = a^b; //相同得0,不同得1
printf("%#x\n", c); //输出0x29,二进制0010 1001
return 0;
}
3.宏定义(无参)
1)为什么使用无参宏定义
因为程序中有时可能会出现多次使用的某个特定数值,例如我想用0代表上,1代表下,2代表左,3代表右,在开发过程中这样的数值不好记忆使用,对阅读程序的人也是一种折磨,这时候使用无参宏定义就可以解决这个问题,将这样特定的数值用自定义的名字来代替,可以增强程序的可读性。
2)定义无参宏
#define 宏定义名字 值
3)举例说明
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//上下左右
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
int main()
{
srand(time(0));
int dir = rand()%4;
if(dir == UP) printf("UP is %d\n",dir);
else if(dir == DOWN) printf("DOWN is %d\n",dir);
else if(dir == LEFT) printf("LEFT is %d\n",dir);
else if(dir == RIGHT) printf("RIGHT is %d\n",dir);
else printf("error\n");
return 0;
}
小知识:
1)如何将某个特定位置0?
unsigned char a;
a = a&~(1<<n);//将变量a的n位写0
//例如unsigned char a = 0x1D; 即0001 1101
//a = a&~(1<<5);
//1<<5,1左移5位,即0001 0000
//按位取反,即1110 1111
//按位与,有0得0,结果为0000 1101
//a == 0x0D
2)如何将某个特定位置1?
unsigned char a;
a = a|1<<n;
//a = 0x20,即0010 0000
//a = a|1<<5;
//1左移5位,即0001 0000
//按位或,有1得1
//a == 0x30,即0011 0000