逻辑运算符:!非 &&与(可以理解为乘法) ||或(可以理解为加法)
异或:0^0 =1 按位取反 : ~1=0 左移:《(移位运算如果是左移n位,将该数乘以2的n次方,右移就是除)
10. switch语句
格式:
switch(表达式){
case常量表达式1: 语句1; break;
case常量表达式2: 语句2; break;
…
case常量表达式n: 语句n; break;
default:语句n+1;} //注意case后面可以有多条语句,可以不用大括号,但是要有break跳出switch语句。
11. 循环语句
while和for
while( ) true进入循环体,false退出
a. 循环一定要有循环条件变量i
b. 一定要有范围
c. 一定要达到这个范围(累加或累减)
for(表达式;表达式;表达式)更简洁
12. 数组(数组名是数组的首地址)
sizeof( int ) , 计算对象所占用的字节数,char*指针变量占8个字节(64位,32位4个字节)
getchar()等同于scanf(),但是更有效率,putchar()同理
数组a[N] 其中N一定是个常量,不能是变量;
根据内存图可知数组的地址是连续的,开辟了一个连续的地址空间,下标和索引用来访问数组元素。注意不能把一个数组赋值给另外一个数组,因为数组的地址是一个只读的地址。a[ ] 的元素默认为0。
sizeof(数组名)求的是数组占用字节数,sizeof(a[1])是求一个元素占用的字节数
13. 二维数组
二维数组的命名方式:可以写成a[3][3]={{1},{2},{3}},没给出的默认为0,如果对全部元素赋值了,那可以写成a[][3]的形式,第一维长度可以不填。
二维数组可以理解为多个一维数组,就是每个一维数组的元素都是一个数组。
14. 函数
概念:不是数学上的函数,是指一个功能模块;一个函数就是划分一小块功能,便于修改和调式,避免重复的多次使用代码。
格式:返回类型(void就是没有返回值) 函数名(参数1 , 参数2)
实参:函数调用的参数,可以传入变量,常量,运算的变量;
实参是通过值传递的,计算实际参数的值赋值给形式参数,参数传递的时候创建副本。数组传递直接传递数组名即数组首地址即可。
形参:函数定义的参数。 //形参实参类型最好一致
return后面跟着的语句可以被调用函数所接受
函数的声明:
格式:int sum(int a ,int b);//封号不能漏,在main上方声明
如果一个函数体放在main函数下面的话,一般出现函数无法调用的错误,这时候就需要函数声明。
15. 递归
函数调用其本身称为递归。//递归一定要有出口!就是递归到最后要return一个值。
16. 局部变量和全局变量
局部变量:自动存储变量,在函数返回的时候会被自动回收。//形参也是局部变量。
全局变量:从变量的声明开始到程序结束。
局部静态变量:作用域是函数内部,值是保存到函数结束。static int a=0;
静态全局变量:只能作用于本文件,其他文件不能导入。
extern I;代表导入一个变量。在同时执行的文件。gcc –o 1 *.c
栈:局部变量和函数参数存放在里面,自动释放;
堆:new分配的内存块,由程序去控制释放;
自由存储区:和堆类似,malloc分配,free释放;
常量区:存放常量,不许修改。
17. 指针
格式:int *p =&a;(这样定义可以清楚的知道指针变量p就是等于a的地址)
概念:指针就是存放一个变量的地址!p=&a;*p=a地址存储空间中存放的值!//其实定义指针变量*和指针*可以理解为不同的符号,如果把定义*改为%就好理解了。
指针变量也是变量,所以也有声明和初始化。
i=*p++相当于i=*p;p++;
间接运算符(重点):间接赋值是指针的重点!*p就是a的值,p就是a的地址!
18. 指针的用途
把指针作为形式参数,间接引用,传递的是地址,实参会改变,参数改变发生在栈销毁之前;
注意和参数传递不同:参数仅是创建了一个副本,实际参数不会改变。
指针可以加减,不可乘除。
指针的偏移与指针的类型相关,指针类型占几个字节,偏移几个字节。
//两个指针相减等于两个指针间的距离(位数)除以指针类型所占字节数。
19. const
const int* p; //间接引用的值不能改变,地址能改变,*p=2不可以(*p只读),可以p++;
const *int p; //p++不可以,*p=2可以改变
主要是看const修饰的是*p还是p,修饰谁,谁就不能改变
int a[]; int b[]; a=b;是错误的,因为数组地址是只读的。
20. 指针和数组的绑定
数组名是只读地址,只需要指向数组的首地址就可以了,绑定了之后就可以像数组那样访问了。//数组作为函数参数传递,其实传递的就是指针(数组首地址),所以无法确定长度。
21. 字符串
英文”aaa”,字符串末尾会默认加\0,所以”aaa”占4个字节。”\0” ascii 为0,0的ascii为48。
字符串的初始化:
char[5] = {‘a’,’b’,’c’,’d’,’\0’} 与char[5] = “abcd”一样。编译期会自动在数组空余位添加\0。//%s输出字符串
字符串的读取格式化参数是%s,scanf不能取地址,scanf参数是指针。如char a[10];scanf(“%s”,a);
scanf 和gets的区别:遇到空白或回车结束读取,gets是一遇到回车就结束。scanf不能读入空格,读入空格代表字符串读取完成。
printf和puts的区别:puts会自动加\n。
字符串和字符指针:
char a[] = “abcd”;
char *a = “abcd”;
字符串存在一个只读字符串常量区,指针式指向字符串常量区域,不能修改只读区域数据;而数组是由字符串常量区拷贝到内存数组中,所以可以修改。
22. 字符串常用api
字符串api需要导入#include头文件
char *strcpy( a,b);//把b字符串复制到a
int strcmp(a,b);//字符串a与b是否相等,返回0代表相等,1代表不相等
charstrcat(a,b);//把字符串b中拷贝到a中,接在a后面,注意a的字符串长度是否满足条件。
int strlen(char*s)//求字符串的长度,数\0之前出现了多少个字符
void*memcpy(void *dest, const void src, size)//内存复制到另一块内存
void *memset(void*s, int c, size)//内存清空,size是多大,调用端可用sizeof()得到大小,将s中当前位置后面的size个字节用c替换并返回s;
memset($stu[i],0,sizeof(stu));//其中stu是struct student stu{},用0替换stu[i]所占字节,也就是将stu[i]数据删除。
void*指针(c语言的泛型),万能指针,因为它可以指向任意一个数据类型。
23. 二级指针
int **p; 地址:*p/p[0] 间接引用的值:**p/p[0][0]/*p[0]
可以这么理解:指向一维数组的指针为一级指针,指向一级指针(一维数组)的指针为二级指针。
二级指针作为参数传递:
一级指针作为参数的时候是改变引用的值,二级指针传参改变的是地址。
二级指针的遍历:
char *p[] = {“abc”,””def”,”hi”};
for(i=0;i<3;i++){printf(“%s”,p[i]);)
24. 常识操作
int a = s[0] -'0'; //s[0]是char类型,用s[0]的ascii码减去‘0’的ascii码得到int型s[0],常用在数字型字符串
全局:是在一个路径下都能访问
局部:只能在可执行程序的路径下访问,并且要加./
命令行参数:就是加在可执行程序后面的参数//如ls、cd都是程序
main函数也要传递参数 int main(int argc参数个数,int *argv[]);注意传递参数的末尾是\0。
atoi(c)将字符转化为整形
预处理阶段:文件包含,宏替换。
文件包:含就是由#include定义的文件
宏替换:由#define定义的指令。//尽量在宏的参数上加括号,防止优先级问题。
预处理的指令:(预处理→编译生成汇编语言→汇编成机器语言)
gcc -E 1.c -0 1.i
注意:不能把预处理指令与定义变量作比较,预处理仅仅是替换而已。而且不检查语法规则。
#:字符串化 如#define S(a) #a,其实就是将变量a上面加了个引号“a”,不负责运算。
##: 符合拼接的意思,如#definefunc(a) func##a 替换后变成了funca
__LINE__显示所在的行,__FUNCTION__显示所在的函数名,__FILE__显示所在的文件名称.// 两个下划线
printf("line:%d func:%s file:%s\n”,_LINE_,_FUNCTION_,_FILE_);
程序调试的时候用打印
25. 结构体
结构体就是不同类型成员的集合。
结构体的声明:
struct ZUO{ struct ZUO{ struct{
intx; intx; int x;
inty; inty; int y;
intz;}; intz;}aa={1,2,3}; int z;}aa={1,2,3};
成员变量就是结构体里面的元素,结构体也是一个构造函数。
第一种struts ZUO是类型 ,第二种aa是struts ZUO定义的类型,第三种aa是此结构体定义的变量,这种只能定义一个变量,一般用于内嵌结构体。
初始化:第一种 struct ZUO aa={1,2,3};第二种、第三种如上,用的少。
对结构体数值型成员赋值zuo.x = 10; 结构体可以赋值,但是类型要一致,比如都是ZUO类型。
结构体传参:
voidchange(struct ZUO* p){ p->x=10;} 格式:结构体指针->结构体成员
结构体字符串赋值用strcpy(aa.name,“hi”);
注意:不能将一个结构体变量作为一个整体引用,要对成员分别应用
26. 共用体和枚举
linux操作系统以4个字节进行内存对齐。内存是如何对齐的:编译器根据类型大小填充字节数,一般是4个字节的整数倍。如果不满4个字节,以4字节填充。超过,就以4个字节对齐。
对齐的理由:保证移植性和性能。保证移植的时候不会出错;保证cpu对内存访问只访问一次,而不是多次。
结构体数组的初始化:
struct stu st[10];
strcpy(st[0].name,"zhangsan");
stu[0].age = 16;
================================
strcpy(st[0],"nan");
union AA{
int a;
int b;
};
说明联合只有一个成员存在,联合的长度以最长的数据类型算。
枚举:enum A{N=10};等同于 #define N 10 和 const int N=10;
枚举中间是逗号:如enumcolor{red=1,yellow=2,blue=3};
枚举有个奇怪的地方就是使用时在main函数可以直接定义一个枚举变量后,就可以直接用枚举种的参数,如同#define替换。
27.Make
工程管理器,能够管理较多的文件。Make可以根据文件时间戳自动发现更新过的文件而减少编译的工作量。同时,它通过读入Makefile文件的内容来执行大量的编译工作。//Make只编译改动的代码,而不用完全编译。