目录
一、关键词static
在C语言中:
static是用来修饰变量和函数的
1. 修饰局部变量-称为静态局部变量
2. 修饰全局变量-称为静态全局变量
3. 修饰函数-称为静态函数
-
修饰局部变量-称为静态局部变量
下面这行代码结果是多少呢?
#include <stdio.h>
void test()
{
int n = 1;
n++;
printf("%d ", n);
}
int main()
{
int i = 0;
while (i < 10)
{
test();
i++;
}
printf("\n");
return 0;
}
结果如下:
加了static修饰后的局部变量n:
#include <stdio.h>
void test()
{
static int n = 1;
n++;
printf("%d ", n);
}
int main()
{
int i = 0;
while (i < 10)
{
test();
i++;
}
printf("\n");
return 0;
}
那结果是多少呢?
看到这里是不是有些同学会感到疑惑:为什么加了static修饰之后代码会变成这样?
stastic到底是个什么东西?怎么用啊?
要想完全理解,我们首先需要知道内存的划分和管理:
第一个代码中创建的局部变量 int n = 1 储存在栈区,其生命周期是:
void test()
{
int n = 1;
n++;
printf("%d ", n);
}
从调用 test()函数开始,到 test()函数结束,每次调用时创建,结束时销毁,所以打印的结果时是十个2。
但是当第二个代码中的局部变量被 static 修饰时,改变了局部变量的储存类型,原本局部变量是储存在栈区的,经过 static 修饰后该局部变量储存在了静态区,储存在静态区的变量出了它的作用域时不会销毁 ,其生命周期与程序的生命周期相同,但其作用域不变。所以,第二个代码打印出来的是2到11。
-
修饰全局变量-称为静态全局变量
用下图代码理解一下全局变量:
extern是用来声明外部符号的;
由上图代码可以看出:全局变量具有外部链接属性。
但当全局变量被static修饰时:
由此可以得出:static修饰全局变量时,改变了全局变量的链接属性;
本来一个全局变量是具有外部链接属性的,但被static修饰之后就变成了内部连接属性,这时,被static修饰的全局变量只能在本源文件(.c)中使用,其它文件无法在使用到。
-
修饰函数-称为静态函数
用下图代码理解一下函数:
extern是用来声明外部函数的;
但当函数被static修饰时:
代码会报错,由此可以得出:
static修饰函数和修饰全局变量是类似的,一个函数本来是具有外部链接属性的,但是当函数被static修饰时,外部链接属性就变成了内部连接属性,函数就只能在本源文件中使用,不能在外部文件中使用了。
二、#define定义常量和宏
-
#define定义常量
#define NUM 100
#define STR "hehe"
#include <stdio.h>
int main()
{
printf("%d\n", NUM);//printf("%d\n", 100);
printf("%s\n", STR);//printf("%s\n", "hehe");
return 0;
}
运行的结果为:
-
#define定义宏
#define ADD(x,y) ((x)+(y))
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
int sum = ADD(a, b);//int sum = (a+b);
printf("%d\n", sum);
return 0;
}
特别注意:ADD(x,y)((x)+(y))后面表达式的两个变量必须分别用括号括起来;
运行的结果为:
三、初识指针
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址,而指针即为地址。
内存单元有编号(地址/指针)
*pa:通过 * 这个解引用操作符找到pa这个指针变量所储存的地址的所指向的对象——a,
然后再对a进行赋值。
思考下面的代码:
#include <stdio.h>
int main()
{
char ch = 'w';
int n = 100;
double d = 3.14;
char* pc = &ch;
int* pi = &n;
double* pd = &d;
printf("%d\n", sizeof(pc));
printf("%d\n", sizeof(pi));
printf("%d\n", sizeof(pd));
return 0;
}
结果是:
为什么 char类型的变量、int类型的变量和double类型的变量所打印的结果一样呢?
因为pc、pi、pd都是指针变量,而指针变量是储存地址的,地址的存放需要多大的空间,指针变量的大小就应该是多大。
并且32位机器 - 支持32位虚拟地址空间 - 产生的地址就是32bit位 -需要32bit的空间存储4byte - 指针变量的大小是4byte;
64位机器 - 支持64位虚拟地址空间 - 产生的地址就是64bit位 -需要64bit的空间存储8byte - 指针变量的大小是8byte
由于我的是32位的,所以结果为4。
四、初识结构体
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。
这里只能使用结构体来描述了。
例如:
描述一个学生
创建的一个学生类型
struct Stu
{
char name[20];
int age;
char sex[5];
double score;
};
int main()
{
struct Stu s1 ;
scanf("%s %d %s %lf", s1.name, &(s1.age), s1.sex, &(s1.score));
//结构成员访问操作符
//结构体变量.结构体成员
struct Stu * ps = &s1;
//printf("%s %d %s %lf\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).score);
printf("%s %d %s %lf\n", ps->name, ps->age, ps->sex, ps->score);
//-> 结构成员访问操作符
//结构体指针->结构体成员
return 0;
}
注:输入结构体中数组时不能写成 (&数组名),因为数组名本身就表示了数组首元素的地址,再加上一个 & 的话,表示的是整个数组的地址,产生歧义,虽然有时候写成(&数组名)运行的结果是正确的,但是这样写一点也不严谨,未来面试考试的话都是会扣分的!!
最后共勉: