1.函数调用流程
普通函数存在栈的开销问题,而宏函数则不存在。
/*宏函数:不是一个真正的函数,在一定场景下比函数效率高,
只是预处理器进行简单的文本替换*/
#define MYADD(x,y) ((x)+(y))
int main()
{
int a = 10;
int b = 20;
//以空间换时间,对于频繁使用且短小的函数,使用宏函数代替
printf("a + b = %d\n", MYADD(a, b));
return 0;
}
2.函数的调用惯例
3.函数变量传递分析
4.栈的生长方向和内存存放方向
//栈的生长方向,a的地址大于b的地址,所以生长方向向下
void test()
{
int a = 10;
int b = 20;
int c = 30;
int d = 40;
printf("a = %d\n", &a);
printf("b = %d\n", &b);
printf("c = %d\n", &c);
printf("d = %d\n", &d);
}
//内存生长方向(小端模式)
void test()
{
//高位字节 -> 低位字节
int num = 0xaabbccdd;
unsigned char* p = #
//从首地址开始的第一个字节
printf("%x\n", *p);
printf("%x\n", *(p+1));
printf("%x\n", *(p+2));
}
小端模式:高位字节放在高地址,低位字节放在低地址
5.指针也是一种数据类型
5.1 指针变量
指针是一种数据类型,占用内存空间,用来保存内存地址
void test()
{
int* p1 = 0x1234;
int* p2 = 0x1111;
//指针是变量,指针本身也占内存空间,指针也可以被赋值
int a = 10;
p1 = &a;
printf("p1 address = %p\n", &p1);
printf("p1 address = %p\n", p1);
printf("a address = %p\n", &a);
//p1的地址是FA88,p1的值为a的地址,所以后两行的值相同
}
指针不管什么类型,几级指针,32位环境下占4个字节(测试环境为win10 64位系统,所以字节数为8)
void test()
{
int* p1 = 0x1234;
int* p2 = 0x1111;
printf("p1 size = %d\n", sizeof(p1));
printf("p2 size = %d\n", sizeof(p2));
}
5.2 空指针
void test()
{
char* p = NULL;
//给p指向的内存区域拷贝内容
strcpy(p, "1111");//报错
char* q = 0x1234;
//给q指向的内存区域拷贝内容
strcpy(q, "1111");//报错
}
5.3 野指针
5.4 间接访问操作符
//解引用
void test()
{
//定义指针
int* p = NULL;
//指针指向谁,就把谁的地址赋给指针
int a = 10;
p = &a;
*p = 20;//*号在等号左边当左值,必须确保内存可写
int b = *p;//*号放等号右边,从内存中读值
}