梓益C语言学习总结
一、静态变量与普通变量的区别
1.1、普通的全局变量
概念:
在函数外部定义的变量
作用范围:
全局变量的作用范围,是程序的所有地方。
只不过用之前需要声明。声明方法 extern int num; 声明的时候,不要赋值。
生命周期:
程序运行的整个过程,一直存在,直到程序结束。
注意:定义普通的全局变量的时候,如果不赋初值,它的值默认为0
1.2、静态全局变量 static
概念:
定义全局变量的时候,前面用static 修饰。
作用范围:
static 限定了静态全局变量的,作用范围
只能在它定义的.c(源文件)中有效
生命周期:
在程序的整个运行过程中,一直存在。
注意:定义静态全局变量的时候,如果不赋初值,它的值默认为0
2.1、普通的局部变量
概念:
在函数内部定义的,或者复合语句中定义的变量
作用范围:
在函数中定义的变量,在函数中有效
在复合语句中定义的,在复合语句中有效。
生命周期:
在函数调用之前,局部变量不占用空间,调用函数的时候,才为局部变量开辟空间,函数结束了,局部变量就释放了。
在复合语句中定义的亦如此。
注意:定义局部变量的时候,如果不赋初值,它的值为随机值
2.2、静态的局部变量
概念:
定义局部变量的时候,前面加static 修饰
作用范围:
在它定义的函数或复合语句中有效。
生命周期:
第一次调用函数的时候,开辟空间赋值,函数结束后,不释放,以后再调用函数的时候,就不再为其开辟空间,也不赋初值,
用的是以前的那个变量。
注意:
1:定义普通局部变量,如果不赋初值,它的值是随机的。
2:定义静态局部变量,如果不赋初值,它的值是0
3:普通全局变量和静态全局变量如果不赋初值,它的值为0
二、头文件路径
#include<> 在系统路径下查找头文件
#include“ ” 在当前目录下查找头文件
三、a++ 先调用a再把它的值加一,++a 先把a的值加一再调用a
四、宏定义 #define
1、宏定义后不加分号,宏定义的值不能改变
2、宏是在预编译的时候进行替换,无变量,不占内存
3、宏定义可以防止不知含义的数字出现,方便修改
4、可以定义任何类型
不带参宏
#define PI 3.14
在预编译的时候如果代码中出现了PI 就用 3.14去替换。
宏的好处:只要修改宏定义,其他地方在预编译的时候就会重新替换。
终止宏:#undef PI //终止PI的作用
带参宏(宏函数)
#define S(a,b) (a)*(b)
注意带参宏的形参 a和b没有类型名,
S(2,4) 将来在预处理的时候替换成 实参替代字符串的形参,其他字符保留,(2) * (4)
五、条件编译(选择性编译)
#ifdef AAA
代码段一
#else
代码段二
#endif
如果在当前.c ifdef 上边定义过AAA ,就编译代码段一,否则编译代码段二
常用在.h文件头部,如:文件fun.h开头写上
#ifndef FUN_H
# define FUN_H
.......代码段.......
# endif
防止fun.h文件被重复引用
六、动态库和静态库
一:动态编译
动态编译使用的是动态库文件进行编译
gcc hello.c -o hello
咱们使用的是动态编译方法
二:静态编译
静态编译使用的静态库文件进行编译
gcc -static hello.c -o hello
三:静态编译和动态编译区别
1:使用的库文件的格式不一样,动态编译使用动态库,静态编译使用静态库
注意:
1:静态编译要把静态库文件打包编译到可执行程序中。
2:动态编译不会把动态库文件打包编译到可执行程序中,它只是编译链接关系
制作静态库:.c文件mylib.c
gcc -c mylib.c -o mylib.o生成mylib.o
ar rc libtestlib.a mylib.o生成静态库libtestlib.a
注意:静态库起名的时候必须以lib开头以.a结尾
编译程序:gcc -static mytest.c libtestlib.a -o mytest
制作动态链接库:gcc -shared mylib.c -o libtestlib.so //使用gcc编译、制作动态链接库
动态链接库的使用:gcc mytest.c libtestlib.so -o mytest
七、
出现段错误,一定是指针用错了
定义字符数组时,记得初始化为空 char str[20]=" ",将空间定义大点,后期可以进行优化
八、创建链表的两种方法
头插法-有返回值
(STU *)link_creat_head(STU *p_head,STU *p_new)
{
if(p_head==NULL) //当第一次加入链表为空时,head执行p_new
{
p_head=p_new;
p_new->next=NULL;
}
else //第二次及以后加入链表
{
p_new->next=p_head; //将新申请的节点加入链表
p_head=p_new;
}
return p_head;
}
尾插法-无返回值
void link_creat_head(STU **p_head,STU *p_new)
{
STU *p_mov=*p_head;
if(*p_head==NULL) //当第一次加入链表为空时,head执行p_new
{
*p_head=p_new;
p_new->next=NULL;
}
else //第二次及以后加入链表
{
while(p_mov->next!=NULL)
{
p_mov=p_mov->next; //找到原有链表的最后一个节点
}
p_mov->next=p_new; //将新申请的节点加入链表
p_new->next=NULL;
}
}
链表逆序:每个节点的next指针的方向调头反向
STU *reverse(STU *head)
{
STU *pf,*pb,*r;
pf=head;
pb=pf->next;
while(pb!=NULL)
{
r=pb->next;
pb->next=pf;
pf=pb;
pb=r;
}
head->next=NULL;
head=pf;
return head;
}
九、fgets
stdout、stdin 标准输入输出缓冲区指针
用fgets代替scanf进行输入读取,避免缓冲区溢出
buf1[20]=" ";
fgets(buf1, sizeof(buf1)-1, stdin);
buf1(strlen(buf1)-1)='\0';
printf("%s\n", buf1);
如果和scanf一起用,要先读出缓冲区中的\n, char ch=0; scanf("%c", &ch);
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。