作者前言
第二篇总计差不多4个小时的番茄钟写完,大概是给自己一个复习,发现之前课上很多知识和概念都没有记清楚。
希望赶紧把C++复习完,然后整个寒假把C语言学完,加油啊啊啊啊啊啊!!,虽然有很多我才看到第55期,总共有200期!!!!
我先死了┏┛墓┗┓...(((m-__-)m。
这期我们要学什么呢?
- 关键字
- 常量和宏
- 指针
- 结构体
关键字
C语言提供的关键字
1.不能够自己创建关键字。
2.变量名不能够是关键字。
auto:
其实每个局部变量都是auto变量。
int main()
{
{
int a = 10;//出了大括号销毁,自动创建,自动销毁
} // 因为局部变量都是auto变量,就直接省略了,后续还有auto相关的用法。
return 0;
}
register
寄存器关键字。
int main()
{
register int num = 100; // 建议num的值存放在寄存器里面。
return 0;
}
计算机中数据的存储:内存,硬盘,网盘,高速缓存,寄存器。
寄存器 更小
高速缓存 几十个MB
内存 8G-16G
硬盘 500G - 买的
网盘 2T——免费
越往上造价越高速度越快,空间越小。
因为CPU的速度越来越快,性能越好导致内存的性能无法跟上cpu的速度,CPU处于闲置状态。
所以我们就将内存内的东西转移到高速缓存,再从高速缓存转移到寄存,CPU则在寄存器中搜索。因为寄存器的速度很快,所以基本上都能够找到,只有在实在不行的情况下,我们才会到高速缓存,再到内存去取。
所以大量频繁使用的数据,就放在寄存器中提升性能。
signed unsigned
signed 是有符号的,有符号位。即有负数
unsigned 就是无符号位,没有负数。
typedef unsigned int u_int;// 使非常长的命名简化重命名。
int main()
{
unsigned int num1 = 100;
u_int num2 = 100;
return 0;
}
static
static静态
1. static修饰局部变量
void test()
{
int a = 1;
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while(i < 10)
{
test();
i++;
}
return 0;
}
如果我们在test函数里面,在a的旁边加上static。
static修饰的局部变量的生命周期变长了,出了{}不销毁。(本质上是改变了变量类型)
2. static修饰全局变量
1.cpp:
extern int g_val;
int main()
{
printf("%d\n", g_val);
return 0;
}
2.cpp:
static int g_val = 2022;
没有加static的时候,全局变量是可以在整个工程中使用的。但如果我们加入了static,当我们在1.cpp运行的时候,就会报错。
static修饰全局变量,使得这个全局变量只能够在自己所在的源文件内部使用。
全局变量,能在其他源文件内部可以被使用,是因为全局变量具有外部链接的属性。
但是被static修饰之后,就变成了内部链接属性,其他文件内部是不能够链接到这个静态的全局变量。
3. static修饰函数
1.cpp
extern int Add(int, int);
int main()
{
int a = 10;
int b = 20;
int c = Add(a, b);
printf("%d\n", c);
return 0;
}
2.cpp
int Add(int x, int y)
{
return x + y;
}
当我们要声明函数的时候,我们就只需要大概告诉函数是什么,类型是什么就可以了。
当我们在2.cpp中的函数旁边加上static,就会报错。
static修饰函数,使得函数只能在自己所在的源文件内部使用,不能够在其他源文件中使用。
volatile c语言暂时不讲。
define 和 include都不是关键字,是预处理指令。
#define定义常量和宏
常量
#define MAX 1000
int main()
{
printf("%d\n", MAX);
return 0;
}
宏
#define ADD(X, Y) X + Y
int main()
{
printf("%d\n", 4*ADD(2, 3));
return 0;
}
这里我们像前面函数定义一样定义宏,注意不要加上=。我们这里会认为2+3 = 5,然后5再乘上4就是20。
为什么会是11呢,这里是因为我们定义宏是替换实际上是 4*2 + 3。是直接替换而不是先计算函数内。
所以我们就可以这么改。
#define ADD(x, y) ((x) + (y))
int main()
{
printf("%d\n", 4*ADD(2, 3));
return 0;
}
指针:
我们的内存就像是宾馆内的不同门牌号的房间。
我们的内存是如何编号的?
32位 - 32根地址线 - 物理线 - 通电 - 1/0
电信号转换为数字信号:1和0的二进制序列。
0000000000000000000000000000
。。。
01111111111111111111111111111111
1000000000000000000000000000
。。。
111111111111111111111111111111
总共2^32的内存单元。假设一个内存单元是1bit,我们就能管理2^32bit位。
因为我们char的单位为字节,即8个bite,可以看出如果内存单位为1个bit,那么结果就会分的过于细致。所以最终我们将一个内存单元分为1个字节。
int main()
{
int a = 10;// 内存中要分配对的大小——四个字节。
return 0;
}
我们可以通过调试来看一个int占据多少字节在内存里。
第一步的地方我们可以输入&a,&就是取地址,我们取出a的地址,step2监视里显示&a
的第一个地址值。我们可以看到44,45,46, 47就可以看到我们a的大小。
int main()
{
int a = 10;
printf("%p\n", &a);
return 0;
}
我们printf的时候我们用%p来接受地址。
int * pa = &a;
// * 说明pa是指针变量
// int 说明pa执行的对象是int类型。
char ch = 'w';
char * pc = &ch;
* 作为解引用符号,我们可以用指针给变量赋值。
int main()
{
int num = 10;
int* p = #
*p = 20;// * 解引用操作 *pa就是通过pa的地址,找到a
printf("%d\n", num);
return 0;
}
我们通过地址p来找到num的位置,然后改变num的值。
我们也可以看看指针的大小。
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(long*));
printf("%d\n", sizeof(long long*));
printf("%d\n", sizeof(float*));
printf("%d\n", sizeof(double*));
return 0;
}
指针的大小我们可以很容易知道是取决于地址的大小,那么我们如果是64位的程序那么,代表着64bit,那么就是8个字节。如果是32位的程序,那么就是4个字节。
当我们把step1中改成x86,那么我们就会发现结果是4。
结构体:
结构体可以用来表示一个复杂的对象,比如人,书等的各个属性。
struct Stu
{
char name[20];// 成员变量
int age;
double score;
};
struct Book
{
char name[20];
float price;
char id[30];
};
int main()
{
struct Stu s = { "张三", 20, 85.5 };
printf("1:%s %d %lf\n", s.name, s.age, s.score);//结构体变量.成员变量
struct Stu* ps = &s;
printf("2: %s %d %lf\n", (*ps).name, (*ps).age, (*ps).score);// 取出变量.成员变量
printf("3: %s %d %lf\n", ps->name, ps->age, ps->score);// 指针 -> 成员变量
return 0;
}
1用的是成员变量本身来打印,2和3就是取成员变量的地址,从地址找到对应的变量打印出来。
芜湖!!!!! 四个番茄钟写完第三篇,我们的基础篇就结束了!!!!!!