1.计算机数据存储:
{
二进制 八进制 十进制 十六进制
基数:
位权:
二进制:
基数:2 0,1
二进制转十进制:加权
十进制转二进制:除二取余倒叙法
八进制:{
基数:8 0-7
前导:0 0123
八进制转十进制:加权
八进制转而进制:
一位八进制用3位二进制表示
0123-001 010 011(从后往前,缺位用0补充)
}
十进制:10 0-9
十六进制:{
基数:16 0-15 -->0-f
10:A/a
11:B/b
13:C/c
14:D/d
15:E/e
前导:0x六进制转十进制:加权
0x123=1*16^2+2*16^1+3*16^0
十六进制转二进制:一位十六进制用四位二进制表示
十六进制转八进制,先转八进制在转八进制(注意往高位补零)
}
2.非数值数据{ 在C语言中字符用 ‘’ 括起来。字符串 用 “” 括起来
ASCII码表 也叫 字符表 255
第一部分由 00H 到 1FH 共 32 个,
一般用来通讯或作为控制之用,有些字符可显示于屏幕,有些则无法显示在屏幕上,
但能看到其效果(例如换行字符、归位字符)。
第二部分是由 20H 到 7FH 共 96 个,
这 96 个字符是用来表示阿拉伯数字、英文字母大小写和底线、括号等符号,
都可以显示在屏幕上。
ASCII码表:
'0' :48
'A':65
'a':97
空格:32
NULL:0
}
3.词法符号:{
1.关键字:
32个,均为小写
存储类型:auto static register extern const volatile
数据类型:char short int float double
控制语句:if else swith case default for while do goto
辅助控制语句:break continue
求字节长度:sizeof
取别名:typedef
符号:signed unsigned
构造:struct union enum
空类型/泛型类型: void
}
4.标识符:
标识符的命名规则:字母、下划线、数字,不以数字开头且不为关键字。
1.数据类型:{
在32位操作系统下
1.char:{
1个字节,8位
值域:-128~127或0~255
signed char :-2^7~2^7-1
unsigned char :0~2^8-1
正数:原码、反码、补码都一样
反码:原码取反
补码:反码加1
-127:1000 0001
-128的补码:1000 0000
}
2.short:{
2个字节,16位
值域:-32768~32767或0~65535
signed short :-2^15~2^15-1
unsigned short :0~65535
}
3.int:{
4个字节,32位
值域:-2^31~2^31-1或0~2^32-1
signed int :-2^31~2^31-1
unsigned int :0~2^32-1
}
4.浮点型:{
单精度float:{
4个字节,32位
精度:6~7
}
双精度double:{
8个字节,64位
精度:15~16
}
}
5.强制类型转换:{
1.显示转化:(数据类型)变量名
int a = 10;
float f = (float)a;
2.隐式转换
注意:强制类型转换不会改变变量的数据类型
}
6.常量:{
定义:在程序运行过程中,值不被修改
12 ‘A' 023 0x123 ”hello“
整型常量:{
123 067 0x12
}
字符常量:{
’c‘ ‘G’
用单引号引起来的单个字符(单单)
'ddd' -->不合法
'\0' '\t' '\n' ‘\\' -->合法
}
字符串常量:{
用双引号引起来的,以'\0'结尾
“hello world” “你好” ”9“
}
标识常量:{
宏(define)
#define 标识常量名 常量
#define MAX 10
注意:原样展开
}
浮点常量:{
小数:0.125
}
指数常量:{
形式:[+/-]M.N e/E [+/-]T
注意:e/E前e/E必有数,e/E必为正数
-1e0.7 -->不合法
0.2e2 --> 0.2*10^2
}
}
}
6.变量:{
一般形式:【存储类型】【数据类型】【变量名】
存储类型:{
auto: 自动存储类型,可省,默认为auto
register :寄存器存储类型,需要申请,申请失败自动转成auto
static :{
局部变量:定义在模块内,作用在模块内,不赋初值,是个随机值
全局变量:定义在模块外,作用整个文件,不赋初值,系统自动赋0
static修饰局部变量:延长其生命周期,但是作用域不变,初始化时自动赋零;
static修饰全局变量:限制其作用域,但生命周期不变;
static修饰函数:仅在本文件中使用;
}
extern :外部引用
}
}
7.运算符:{
根据操作数分类: 单目运算符、双目运算符、三目运算符
&a a + b (a > b)?a:b
算术运算符:{
+ - * / %
注意:
除法(/):取整数部分,不进行四舍五入 8/3 = 2
取余(%):浮点数不能进行取余
}
逻辑运算符:{
&& || !
运算规则:
0为假,非0为真
逻辑与&&:两边为真才为真
0 && 0 = 0
0 && 1 = 0 有0为假,全1为真
1 && 1 = 1
逻辑或||:一边为真即为真
0 || 0 = 0
0 || 1 = 1 有1出1, 全0为假
1 || 1 = 1
非!:取反
!1 = 0
!0 = 1
短路法则:当编译器得到结果后,就不再往下执行
}
关系运算符:{
< > <= >= ==
}
位运算符:{
对二进制数进行运算
& | ^ ~ << >>
位与&:两边为真才为真
0 & 0 = 0
0 & 1 = 0 有0为假,全1为真
1 & 1 = 1
位或|:一边为真即为真
0 | 0 = 0
0 | 1 = 1 有1出1, 全0为假
1 | 1 = 1
异或^(生小孩符号):0代表女生,1代表男生
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 1 = 0
}
赋值运算符:{
=
复合赋值运算符:{
+= /= *= ^= ~=
a += b --> a = a+b
a *= b --> a = a*b
a <<= 2 --> a = a<<2
}
}
递增递减运算符:{
递增运算符:++ -->操作数自增1
递减运算符:-- -->操作数自减1
a++ --> a = a+1
++a --> a = a+1
a-- --> a = a-1
--a --> a = a-1
注意:加加在前,先加后用;加加在后,先用后加
int a = 2;
++a;//3,a = 3
a++;//3,a = 4
a; //4
}
地址运算符:{
& int a; &a ----> 获取a 的地址。打印 : %p
&变量名
}
逗号运算符:{
(表达式1, 表达式2, 表达式3,... ,表达式n)= 表达式n
注意:从左往右依次计算,取最后一个表达式的结果作为整个逗号表达式的结果
}
sizeof运算符:{
求字节数
sizeof(变量名/数据类型名);
}
其他运算:{
?:
(a > b)?a++:++b --> 真前假后
}
}
8.输入输出:{
C语言没有输入输出语句,不能进行IO操作,使用#include<stdio.h>
1.格式化输入输出:{
格式化输入:
{
scanf("格式控制串", 地址表);
格式控制串:
%i/%d:输入十进制整数
%x/%X:输入十六进制无符号整数
%o:输入八进制无符号整数
%u:输入无符号十进制整数
%c:输入单个字符
%s:输入字符串
%e:输入指数形式的浮点小数
%f:输入小数形式的浮点小数
注意:在格式控制串中不要写'\n'
}
格式化输出函数:{
printf(“格式控制串”, 输出表);
格式控制串:1.%[修饰符],格式字符,用于指定输出格式
2.普通字符,原样输出
格式符:
%i/%d:输出十进制整数
%x/%X:输出十六进制无符号整数
%o:输出八进制无符号整数
%u:输出无符号十进制整数
%c:输出单个字符
%s:输出字符串
%e/E:输出指数形式的浮点小数
%f:输出小数形式的浮点小数
%g:输出e和f中较短一种
%%:输出百分号本身
修饰符:
m:输出数据域宽,数据长度<m,左补空格,否则原样输出
int a = 123
printf("%5d %2d\n", a, a); ---> __123 123(我用下划线表示空格)
.n:对实数,指定小数点后几位数(四舍五入)
对字符串,指定时间输出位数
float f = 12.3
char s[5] = "hello"
printf("%08.3f, %.3", f, s); --> 0012.300, hel
-:输出数据在域内左对齐(缺省右对齐)
0:输出数值时指定左面不是要的空位置自动填0
#:显示输出八进制和十进制的前导
}
}
2.字符的输入输出:{
输入:getchar();
char c;
c = getchar();
输出:putchar();
putchar(c);
注意:putchar不带换行
}
3.字符串的输入输出:{
输入:gets();
char str[20];
gets(str);
输出:puts();
puts(str);
注意:puts()带换行
}
4.“垃圾字符”的处理
1.getchar();
2.%*c或scanf("%d ",&a),添加空格
}
9.控制语句:
顺序、分支(选择)、循环
分支:{
1.if-else:{
1.简易结构
if(表达式)
{
语句序列1;
}
else
{
语句序列2;
}
注意:1.语句序列如果只有一句,可以不写花括号,但是有多句就一定要写
2.else后面没有表达式
2.阶梯形式:{
if-else-if
if(表达1)
{
语句序列1;
}
else if(表达式2)
{
语句序列2;
}
else if(表达3)
{
语句序列3;
}
...
else
{
语句序列n;
}
3.嵌套形式:{
if(表达式4)
{
if(表达式3)
{
if(表达式2)
{
if(表达1)
{
语句序列1.1;
}
else
{
语句序列1.2;
}
}
else
{
语句序列2;
}
}
else
{
语句序列3;
}
}
else
{
语句序列4;
}
注意:嵌套的层次不要太深
}
注意:else总是与上一个未配对的if配对
}
2.switch语句:{
switch (表达式)
{ case 常量表达式1:语句块1;break;
case 常量表达式2:语句块2; break;
….
case 常量表达式n:语句块n; break;
default :语句块n+1;
}
注意:switch表达式不能为浮点型
}
3.循环结构:{
1.for:{
一般形式:for(表达式1;表达式2;表达式3)
{
语句序列;
}
1.表达式1,只做一次,可省,前提是变量初始化
2.判断表达式2, 表达式2,也可省,死循环
3.表达式3:也可省,在语句序列里进行变量的操作
4。三个表达式可以同时省,形成死循环for(;;);
}
2.while:{
一般形式:while(表达式)
{
语句序列;
}
}
3.do-while:{
一般形式:do{
语句序列;
}while(表达式);
}
4.goto:{
跳转
flag:
语句序列;
goto flag;
}
6.辅助控制:{
break :结束本轮循环
continue :结束本次循环,继续下一次循环(即continue以下的语句不执行)
}
10.数组:{
1.定义:是一个具有一定顺序的若干相同数据类型的集合
2.一般形式:存储类型 数据类型 数组名[表达式];
auto int a[10];
3.一维维数:{
1.一般形式:存储类型 数据类型 数组名[表达式];
auto int a[10];
2.注意:表达式不能是变量
int n = 10;
int a[n]; --> 错误!!!
#define N 20
int a[N]; --> 正确!!!
3.存储形式:
4.数组元素的引用:数组名[下标]
注意:1.下标从0开始
2.对数组元素的使用,必须单个使用
5.数组的初始化:{
1.完全初始化:int a[5] = {1,2,3,4,5};
2.部分初始化:int b[5] = {1,2};//未初始化部分,系统自动赋0
3.特殊初始化:int c[] = {1,2,3,4,5};//维数不写,系统帮我们数,维数5
注意:维数和元素个数,必须要写一个
int d[] = {}; --> NO!
int e[]; --> NO!
}
总结:
1、数组名 地址常量 数组空间首地址 a == &a[0];
2、数组的赋值和打印只能单个进行!!
3、取元素,通过下标的方式取每个元素,下标从0开始,最大的元素,下标是元素个数-1
4、数组容易越界!! 所以使用的时候要小心!!
就会出现段错误!! 非法访问内存!!
所以说在用数组的时候要注意范围!!!
6.字符型一维数组:{
char str[10];
初始化:
1.完全初始化:char str1[5] = {'a','b','c','d','\0'};
char str2[5] = "abcd";
2.部分初始化:char str3[5] = "ab";//未初始化部分,系统自动赋'\0'
3.特殊初始化:char str4[] = "abcd"//维数是5
注意:当字符串中有多个'\0'时,遇第一个结束
}
3.冒泡排序
}
}
11.二维数组:{
二维数组:由多个一维数组组成
二维数组的初始化:{
1.完全初始化: int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};//int a[3][3] = {1,2,3,4,5,6,7,8,9};
2.部分初始化: int b[3][3] = {{1,2},{4,5},{7,8}};//int b[3][3] = {1,2,4,5,7,8};
3.特殊初始化: int c[][3] = {{1,2,3},{4,5,6},{7,8,9}};//int c[3][3] = {1,2,3,4,5,6,7,8,9};
}
整个二维数组占的字节数:sizeof(a) = 行数 * 列数 * 数据类型
行数 = sizeof(a) / sizeof(a[0])
列数 = sizeof(a[0]) / sizeof(a[0][0])
二维数组名: 也是空间首地址,也是一个地址常量!
a == &a[0] (二维数组名是一维数组的首地址) a == &a[0] == &(&a[0][0])
a[0] == &a[0][0] (一维数组名是第一个元素的首地址!)
字符型二维数组:{
注意:'\0'
一般形式: char str[10][10];
char str1[3][20] = {{"Happy"},{"National"},{"Day!"}};
}
字符串的输入输出{
格式化: scanf("%s",a); a 字符串的首地址!!!
printf("%s",a);
1、printf("%s",a);打印不会自动换行!必须加 '\n'才能换行
2、scanf("%s",a);输入字符串遇见空白字符就结束,(不能输入空白字符,空格等)
字符串的输入输出函数:
gets(a);//输入一个字符串,输到首地址为 a 的位置
puts(a);//打印一个字符串,打印首地址为a 的字符串
特点:
1、puts(a);会自动换行
2、gets(a);可以输入空白字符,只遇到回车结束
3、gets十分危险,他不会做越界判断!以后学到fgets,就要把 gets 抛弃。
4、用gets的时候,自己要小心,字符数组的大小!
}
12.字符串函数:{
1.strcat:{
1.功能:将str2连接到str1后面
strcat(str1, str2);
2.注意:str1要足够大
str1的'\0'要取消,新串后面要添加'\0'
}
2.strcpy:{
1.功能:实现字符串的拷贝
strcpy(str1, str2);
2.注意:str1要足够大
str2的'\0'要拷贝过去
不能使用"="给字符数组赋值, 而要是有strcpy
}
3.strcmp:{
1.功能:比较两个字符串的大小
2.比较规则(返回值):
str1 > str2, 返回正整数
str1 < str2, 返回负整数
str1 == str2, 返回0
3.注意:从左往右逐个比较,直到遇到不同字符或'\0'才停止
不能使用"=="去判断两个字符串是否相等,而要用strcmp
}
}
13.指针:{
1.地址:内存对每一字节单元的编号
32位操作系统下,地址是用4字节的16进制表示(0x0 ~ 0xffffffff)
2.在不影响理解的情况下,地址、指针、指针变量都称之为指针
3.*/&:{
&:取地址运算符
*:指针运算符/解引用
指针变量的一般形式:
存储类型 数据类型 *指针名;
int a = 10;
int *p;
p = &a;
解引用符:1.申明定义一个指针变量
2.取指针所指向变量的内容
取地址运算符和解引用符互为逆运算
}
3.对变量的访问:{
1.直接访问: 通过变量名直接访问
2.间接访问:通过指针
}
4.指针变量:保存变量地址的变量
5.指针变量的初始化:{
int *p = &a;
}
6.空指针:int *p = NULL;
7.直接操作野指针或空指针,都会造成段错误
8.指针的运算:{
指针运算的实质:地址的运算
注意:相同类型之间直接的运算才是有意义的
int a, b[10], *p1, *p2;
1.算数运算:{
+ - ++ --
p1 + n --> 向地址增大的方向移动n数据 // 移动的字节数:n*数据类型
p1 - n --> 向地址减小的方向移动n数据
p1++/++p1 --> 向地址增大的方向移动1数据
p1--/--p1 --> 向地址减小的方向移动1数据
p1 - p2 --> 两个地址间的数据个数//p1 + p2 error
}
2.关系运算:{
< > <= >= == !=
p1 < p2 --> p1的地址小于p2
p1 == p2 --> p1和p2指向同一片内存空间/都为NULL
}
3.赋值运算:{
1.普通变量的地址
p = &a;
2.数组的首地址
p = b;
3.同类型指针之间的赋值
p = &a;
int *q = p;
}
}
}
14.指针与数组:{
1.与一维数组:{
1. char a[10];
char *p;
p = a;//p = &a[5];
2.关系:{
a[i] = *(a+i);
a[3] = *(a+3) = p[3] = *(p+3)
数组名约等于指针,除了自增自减和赋值(数组名本质是地址常量,指针本质是地址变量)
p++ ++p --p p++ p = p+1
}
3.注意指针的当前位置
通过自增、自减、赋值可以改变指针的当前位置
}
2.与二维数组:{
二维数组由多个一维数组组成
}
3.行指针:{
二维数组名加一,跳一行数据,所以二维数组又交行地址
一般形式:存储类型 数据类型 (*行指针名)[列数];
int (*p)[3] --> 表明这个指针变量+1, 跳3个数据
改变指针性质/降维:加*操作
*p+1 --> 跳一个数据
*(*p+1) -->取指针所指向变量的内容
}
}
15.指针数组:{
区分:指针数组和数组指针:{
一般形式:
指针数组: int *p[5];
数组指针: int (*q)[5];
谁在后面本质就是什么
}
}
16.二级指针:{
一般形式:数据类型 ** 二级指针名;
int **p;
保存一级指针的地址叫做二级指针
}
4.const型指针:{
将变量常量化
const int *p; 不能改变指针指向的数值
Int *const p = &m; 不能改变指针存的地址,初始化赋地址;
}
5.void 指针
可以存其他类型的地址,输出时强制类型转换;
函数:{
定义:实现特定功能的代码模块
作用:接口重用
函数的一般形式:{
【数据类型】【函数名】(形式参数说明)
{
语句序列;
return (表达式);
}
1.数据类型:函数返回值的类型{
无返回值:void(空类型)
有返回值:基本数据类型 构造类型(struct) 地址...
注意:有返回值函数调用可以单独写一行也可以不用,无返回值时必须单独写一行
}
2.函数名:遵循标识符的命名规则
3.形式参数说明:简称形参,数据类型、变量名,有多个形参用逗号隔开
4.语句序列:又叫函数体,可以没有函数体
5.return语句:要和数据类型匹配,返回的是表达式,可以进行运算的
}
函数的说明:[数据类型][函数名](形式参数说明);
注意:函数说明时,形参名可以不写,在main函数之上
void fun(int a);
void fun(int );
函数的使用 --> 函数调用
哪里需要就在哪调用
函数名(实际参数);
fun(10);
fun(a);
实际参数简称实参,实参可以是某个变量或者表达式或者常量
函数传参:{
1.基本数据类型作为参数在函数之间传递:{
复制传递(值传递) 地址传递 全局变量
复制传递:{
值传递
将实参的值复制一份传递给形参,形参如何修改都不会影响实参
}
地址传递:{
实参传地址 --> 形参为指针
通过指针访问变量
}
}
2.数组作为参数在函数之间传递:{
复制传递(值传递) 地址传递 全局变量
复制传递和地址传递实质是一样:形参都是指针,只是写法不一样
注意:1.整型数组作为参数在函数之间传递,除了要传数组的首地址外,还需要传数组的长度
2.字符型数组作为参数在函数之间传递,可以不传字符串的长度
}
}
}
函数和指针:
int max();
int (*p)() = &max; // 函数指针 指向函数的指针!
int *q();
函数指针{ 其本质是一个指针
指向函数的指针!!! 它的所有操作和普通指针相同,只是指向一个函数!
格式: <数据类型> (*<指针变量名>)(参数列表);
数据类型: 指针指向的函数的 返回值的数据类型
参数列表: 必须和指针要指向的函数 的参数列表相同
}
指针函数{ 其本质是一个函数!!
就是指 返回值是 指针(地址) 的函数 就叫指针函数
格式: <数据类型> *<函数名>(参数列表);
数据类型 *: 函数返回的是一个 数据类型 *(地址)
参数列表: 函数需要传入的参数
}
}