一、基础知识
1、编译和链接
编译是将C源程序翻译成计算机能识别的0和1,链接是将.o文件和C语言函数库组合在一起,生成可执行文件
2、常见文件的拓展名
.c是C语言源文件,在编写代码的时候创建
.o是目标文件,在编译成功的时候产生
.out是可执行文件,在链接成功的时候产生
3、相关指令
编译:cc –c 文件名.c ,编译成功,会生成.o目标文件
链接:cc 文件名.o,链接成功,会生成a.out可执行文件
运行: ./a.out
修改可执行文件名称:cc xxx.o -o 文件名
一起编译、链接:cc xxx.c
4、常见错误
- 不写分号、用了中文分号
- 字符串少了双引号、或者用了单引号,双引号里面又有双引号
- 代码没有写在main函数内部、return之前
- 文件拓展名不是.c或者.C,比如.txt
- 用绝对路径编译文件,注意目标文件生成的地方
- 语法错误,可以通过编译器的报错信息解决
- 逻辑错误,需要耐心调试程序
5、标识符命名规则
- 只能由26个英文字母的大小写、10个阿拉伯数字0~9、下划线_组成
- 不能以数字开头
- 不可以使用关键字作为标识符
6、数据类型
7、#include的作用纯粹是文件拷贝
在使用stdio.h中声明的函数时要加入#include <stdio.h>。
8、sizeof
用来计算一个变量或者一个常量、一种数据类型所占的内存字节数。
基本形式
sizeof( 变量\常量 )
sizeof( 数据类型 )
二、基本运算
1、算术运算
加、减、乘、除、取余分别用+ - * / % 表示
- + - 还可以表示正负
- 整数除于整数,还是整数,1/2的值是0,1.0/2值0.5
- %两侧只能是整数,正负性取决于%左侧的数值
2、赋值运算
int a = 10 + 5;
a = b = 10;
a += 4 + 5; //复合赋值
- 等号左边不能是常量,比如10 = 11;
3、自增自减
(1)简单使用
++ 自增运算符。如a++,++a,都等价于a = a+1
-- 自减运算符。如a--,--a,都等价于a = a-1
5++是错误的
(2)++a和a++的区别
int a = 10;
int b = a++;其中a=11,b=10
int b = ++a;其中a=11,b=11
4、关系运算(比较运算)
- 条件成立称为“真”,条件不成立称为“假”
- 任何非0值都为“真”,只有0才为“假”。
- 关系运算符中==、!=的优先级相等,<、<=、>、>=的优先级相等,且前者的优先级低于后者
- 关系运算符的结合方向为“从左往右”
- 关系运算符的优先级小于算术运算符
5、逻辑运算
(1)&&逻辑与 “条件A && 条件B”
- 运算结果
只有当条件A和条件B都成立时,结果才为1;其余情况的结果都为0
- 运算过程
总是先判断条件A是否成立,如果条件A成立,接着再判断条件B是否成立
如果条件A不成立,就不会再去判断条件B是否成立
(2)|| 逻辑或 “条件A || 条件B”
- 运算结果
当条件A或条件B只要有一个成立时,结果就为1;只有当条件A和条件B都不成立时,结果才为0
- 运算过程
总是先判断条件A是否成立,如果条件A成立,就不会再去判断条件B是否成立
如果条件A不成立,接着再判断条件B是否成立
(3)! 逻辑非 “! 条件A”
对条件A进行取反:若条件A成立,结果就为0;若条件A不成立,结果就为1。
逻辑非的结合方向是“自右至左”。比如表达式 ! (a>5)
(4)优先级
逻辑运算符的优先级顺序为: 小括号() > 负号 - >!> 算术运算符 > 关系运算符 >&&>||
6、三目运算符
int a = 5?10:2;
获得a、b、c中的最大数
三、程序结构
1、选择结构-if
if (表达式) 语句1;
if(表达式) 语句1; else 语句2;
if(表达式) { }
if -else if-else
2、选择结构-switch
switch(表达式) { case 数值1: break; … default: break;}
3、循环结构-while
(1)简单使用
while(表达式) { }
continue:跳过本次循环
break的使用:停止循环
(2)特点
只有条件成立才会执行循环体
4、循环结构-do while
(1)特点:一定会执行一次循环体
(2)while和do while循环对比
a) while先判断条件再执行循环体,
b) do while先执行循环体再判断条件,至少会执行一次
5、循环结构-for
初始化语句等可以是多句(把printf放到for的括号中)
for (int i = 0; i<5; i++)
{循环体}
死循环 for(;;);
for循环体内部变量的作用域
四、函数
1、定义函数的目的
将一个常用的功能封装起来,方便以后调用
2、定义函数的步骤
函数名:函数叫什么名字
函数体:函数是干啥的,里面包含了什么代码
3、格式
返回值类型 函数名(形式参数列表)
{
函数体
}
举例
sum(int a, int b)
{
return a + b;
}
4、函数调用
sum(10, 11);
5、函数的参数
形参个数和实参一致:sum(10, 11, )
参数的传递是值传递
参数名不能跟函数内的局部变量同名
函数可以没有参数:设计一个函数返回PI
6、函数的返回值
void可以省略return
可以多次使用return
return后面不能有其他语句
7、函数的弱语法
如果没有写返回值类型,默认是int
如果写了返回值,可以不返回
调用一个没有定义过的函数
8、函数注意
不能嵌套定义函数
死循环调用,自己调用自己
不能重复定义、可以重复声明
五、数组
1、数组的特点
只能存放一种类型的数据,比如int类型的数组、float类型的数组
里面存放的数据称为“元素”
2、数组的定义
声明数组的类型
声明数组的元素个数(需要多少存储空间)
3、格式
元素类型数组名[元素个数];
比如:int ages[3];
4、简单使用
简单初始化:int ages[5] = {19, 19, 20, 21, 25};
元素有顺序之分,每个元素都有一个唯一的下标(索引),从0开始
数组元素的访问:a[i]
5、内存分析
数组存储空间的大小
存储空间的划分(内存的分配是从高地址到低地址进行的,但一个数组内部元素又是从低到高进行的)
数组名的作用,查看元素地址
数组越界的注意
六、指针
1、指针变量的定义
(1)定义的格式
类名标识符 *指针变量名;
int *p;
(2)先定义后赋值
l 简单取值
int a = 10;
int *p;
p = &a;
printf(“%d”, *p);
简单改值
*p = 9;
(3)定义的同时赋值
int a = 10;
int *p = &a;
(4)注意点
- int *p; p = 1000;
- int *p; *p = 100;
- int *p; *p = &a;
- %p输出指针里面存储的地址值
- 其他指针类型说明,比如float *p; char *p;
- 不能乱用类型,比如int a = 10; float *p = &a;
(5)清空指针
p = 0;
p = NULL;
2、指针实例
void swap(char *a, char *b)(注意temp=a; a = b; b = temp;)
int sumAndMinus(int a, int b, int *minus)
3、指针与字符串
char *s = “mj”;
或者
char *s;
s = “mj”;
4、指向函数的指针
(1)为什么指针可以指向一个函数?
函数作为一段程序,在内存中也要占据部分存储空间,它也有一个起始地址,即函数的入口地址。函数有自己的地址,我们的指针变量就是用来存储地址的。因此,可以利用一个指针指向一个函数。其中,函数名就代表着函数的地址。
(2)指向函数的指针的定义
定义的一般形式:函数的返回值类型 (*指针变量名)(形参1, 形参2, ...);
(3)使用注意
由于这类指针变量存储的是一个函数的入口地址,所以对它们作加减运算(比如p++)是无意义的
指向函数的指针变量主要有两个用途:
·调用函数
·将函数作为参数在函数间传递