linux基础:c语言基础补习
C基础
一:linux基础 3
1、Linux常用命令 4
2、Vim编辑器 6
二:C基础 6
1、计算机的组成 6
2、计算机的数据表示 8
3、C补习内容 8
4、LinuxC的开发流程 8
5、程序的入口:main()函数 9
6、变量 9
7、基本数据类型(32位操作系统) 9
三:C基础(2) 12
1. 常数如何描述 12
1〉作业:计算一个整数的二进制中1的个数(整数可为正为负) 14
4. 内存值如何查看 16
1〉作业:编写一个猜数字的软件 16
5.控制语句 17
1〉if要点 17
2〉作业:判断一年是否为闰年? 17
3》switch语句 18
四:C基础(3) 19
一〉技术点: 19
1. 溢出越界 19
2. ++i, i++ 19
3. atoi() 20
4.十进制转十六进制: 20
二〉C语句 20
1.分支语句 20
1〉goto与longjmp 20
2〉switch语句 21
3〉Scanf-------从键盘获取数据 21
2.数据类型: 22
1〉enum----枚举 22
2〉void 22
3〉51c------sbit 22
4〉char: 22
5〉字符串常量 22
3.内存: 23
1〉常量 23
2〉变量 23
3〉Static 23
4〉Const 23
六:C基础(5) 23
1、二维数组 23
2、 字符数组 25
3、跟字符串相关的函数 26
1〉strlen 26
2〉strcpy 26
3〉strcat 26
4〉strcmp 26
1〉strcpy()-- 27
2> strcat()--- 27
3〉strlen()- 28
3> Strcmp 29
4〉Int型数组中的次大值 29
5〉打印ab对称图形 30
6〉二维字符数组排序 31
7〉寻找字符串中出现次数最多的字符 32
8〉字符串转换为int-----------已知int为正 33
9〉int(有正有负)转换为char 34
10〉查找特定字符 35
七:C基础(6) 35
一〉一维数组: 35
二〉二维数组 36
三〉一维字符数组: 36
四〉二维字符数组: 36
五〉什么是指针 38
1.指针的定义 38
2、什么是指针变量 38
3、指针的初始化 39
4、指针的访问 39
5、*在C语言中的三种用法 40
6、指针的运算 40
1〉算术运算 40
2〉关系运算 40
7.指针与一维数组 41
六〉作业 42
八:C基础(七) 44
一〉计算机内存分布: 44
二〉二级指针 44
1.指针与二维数组 45
2.指针数组: 46
3.字符指针 47
三〉函数 48
四〉gdb调试工具 49
五〉static 50
六〉作业: 50
九:C基础(8) 51
一〉结构体 51
1. 定义: 51
2、字节对齐 52
3、共同体 52
4、大小端 53
5、 Const 53
4、指针函数: 54
一:linux基础
什么是嵌入式:软件控制的硬件
嵌入式---一个定制的计算机
所以:硬件和软件需要根据设备要实现的功能专门去设计
也就是说嵌入式系统所需要的操作系统是可以被修改的
linux系统是一个开源软件--可以免费得到源代码并且可以自由修改
学习软件:
1、VNC (同屏) server viewr
2、飞秋
3、VM(虚拟机) 虚拟的一台电脑,可以在这台虚拟的电脑上运行linux操作系统
4、ubuntu
LinuxOS windows
ubuntu windowxp
redhat window7
红旗 window10
ubuntu每半年更新一次 04 10
每两年更新一个长期版本(稳定)LST
Linux是一个开源的、多用户的、多任务的操作系统,要求必须以用户和密码去登录
shell:命令行解释器 用户和内核进行沟通的桥梁
shell其实就是程序,程序提供给我们一个界面(终端),这个界面可以让我们输入命令 (shell命令)
1、Linux常用命令
ctrl+alt+t:打开一个终端
命令行提示符-------》 用户名@计算机名:当前路径$
$:代表当前登录的用户是一个普通用户
#:超级用户,root用户,权限最高
su - 用户名:切换到该用户
ctrl+d:从超级用户切换回普通用户
pwd:查看当前路径
sudo:增加权限
绝对路径:从根目录开始的路径
相对路径:具体看参照物
windows的文件系统犹如一片森林,各自独立
Linux的文件系统犹如一颗倒置的树,所有的目录都在跟目录之下
ls:查看当前目录下的内容
ls 目录路径:查看该目录下的内容
ls -a:查看当前路径下的所有内容(包括隐藏文件 以.开头的文件叫隐藏文件)
ls -l :以长格的形式显示当前目录下内容的详细信息
drwxrwxrwx 6 linux linux 4096 Jun 9 20:14 A9Server
d:文件类型
linux下文件分为7种:
- --------->普通文件
d ---------->文件夹
p ----------->管道文件
l ----------->链接文件
b ------------>块设备文件
c ------------>字符设备文件
s ------------->套接字文件
cd:切换目录路径
cd .. :退回上一级目录
cd ../..:退回上一级目录的上一级目录
cd -:返回上一次的目录路径
cd .:返回当前目录
cd ~(cd):快速返回家目录
ctrl+shift+'+':放大字体
ctrl + '-':缩小字体
安装中文:ibus-setup
ctrl+空格:语言切换
clear(ctrl+l):清屏
touch 文件名:创建一个文件(文件名可以多跟)
rm 文件名:删除一个文件
mkdir 文件夹名:创建一个文件夹
mkdir -p :连续创建多级目录
rmdir 文件夹名:删除一个文件夹(只能删除空文件夹)
rm -rf 文件夹名:删除一个文件夹
cp 被复制的文件名 目标路径:
cp -r 被复制的文件夹名 目标路径
cp -i 被复制的文件名 目标路径:提示是否被覆盖
mv 被移动的文件 目标路径:
mv 1.c 2.c ------>2.c不存在则把1.c改名为2.c 存在则先改名然后覆盖
mv day1 day2 ----->day2不存在改名,存在移动
cat 文件名:查看该文件的内容(一般适用于比较短的)
more 文件名:查看该文件的内容(一般适用于比较长的)
按回车:一行一行的向下查看
按q退出
sudo reboot:重启
sudo shutdown -h now:立即关机
sudo shutdown -h 20:20分钟后关机
chmod 777 文件名:把该文件的权限全都打开
Tab:自动补全
向上的箭头:上一次的命令
ctrl+c:结束当前进程
2、Vim编辑器
vim 文件名:如果文件时存在的就直接打开,如果不存在新建该文件再打开
vim的三种模式:命令行模式、插入模式、底行模式
刚打开一个文件是命令行模式,命令行模式---》插入模式(按i) 插入模式---》命令行模式(esc) 命令行模式---》底行模式(shift+:)
命令行模式:
i:从光标所在地方的前面开始插入
I:从光标所在的行首开始插入
a:从光标的下一个字符的前面开始插入
A:从光标所在行的行末开始插入
o:从光标所在的下一行(新建的行)开始插入
O:从光标所在的上一行(新建的行)开始插入
插入模式:在插入模式下才可以编辑文本
底行模式:(以:开始)
:w 保存
:q 退出
:wq 保存并退出 :x ZZ(命令行模式下)
:wq! 强制保存退出
:wq 文件名 以新名字保存的备份文件
:set nu 设置行号
:set nonu 取消行号
:set hlsearch 设置高亮
:range %s/str1/str2/g 在range范围内所有的str1都替换成str2
/str (命令行模式) 查找str
nyy:n代表行数(命令行模式下进行复制粘贴)
p:粘贴
ndd:剪切
u:撤销
=gg (命令行模式下)自动调整格式
gcc编译器,gcc 2.c会默认生成可执行文件a.out,执行 :./a.out
gcc 2.c -o 2将可执行文件a.out改名为2,执行:./2
3.6 文本内容的删除操作;
x 一个字符;
#x 删除几个字符,#表示数字,比如3x;
dw 删除一个单词;
#dw 删除几个单词,#用数字表示,比如3dw表示删除三个单词;
dd 删除一行;
#dd 删除多个行,#代表数字,比如3dd 表示删除光标行及光标的下两行;
d$ 删除光标到行尾的内容;
J 清除光标所处的行与上一行之间的空格,把光标行和上一行接在一起;
二:C基础
1、计算机的组成
硬件
CPU:运算器、控制器(控制从内存获取数据,与内存交换数据很快)、寄存器
存储器:
内部:ROM(只读存储器) RAM(随机存储器,断电后数据易丢失)
外部:硬盘、U盘
输入设备:键盘、鼠标、麦克风
输出设备:显示器、音响、打印机
软件
系统软件:windows linux UNIX
应用软件: wps qq
一台没有任何软件的计算机称为“裸机”。
储存1T是指硬盘的总容量为1TB。太字节(Terabyte),计算机存储容量单位,也常用TB来表示。1TB=1024GB==2^40字节
2、计算机的数据表示
数值数据 非数值数据
数值数据:二进制 十进制 八进制(以0作为前缀,0~7) 十六进制(以0x作为前缀,0~f(F))
十进制转其他进制:除2/8/16倒取余
非数值数据:‘a’ '\n' '5'
3、C补习内容
(1)数据类型
基本数据类型:int float char
复合数据类型:数组、指针、函数、结构体
(2)运算符
(3)结构性语句
顺序语句
选择语句
循环语句
(4)算法
求最大值 冒泡排序
4、LinuxC的开发流程
输入一个数,求这个数是奇数还是偶数
(1)分析建模
num
num%2==0---->偶数
num%2==1---->奇数
(2)画流程图
a.输入一个数num
b.如果num%2==0,输出该数是偶数
c.如果num%2==1,输出该数是奇数
(3)翻译成C代码
(4)编译
(5)运行
5、程序的入口:main()函数
int main()
{
return 0;
}
6、变量
在程序运行过程中其值可以改变的量
7、基本数据类型(32位操作系统)
int (4个字节) [signed]int:-2^31 ~ 2^31-1 unsigned int:0 ~ 2^32-1
short (2个字节)[signed]short:-2^15 ~ 2^15-1 unsigned short:0 ~ 2^16-1
long (4个字节)
long long (8个字节)
float:4个字节
double:8个字节
char:1个字节 [signed]char:-128~127 unsigned char :0~255
看成是一个字节的int
列子:int a=’\101’;//0101;//0x41;//65
Float 1.4;//1.4=14*10-1
(浮点数存储:左边为符号 中间整数存储 右边指数存储)
指数存储占低8位,符号位占高八位
8、标识符的定义(变量名、数组名、函数名)
a.由数字、字母、下划线组成
b.首字母不能是数字
c.不能与关键字重名
d.尽量见名知意
9、关键字
关键字:32个 由系统定义的 全都是小写
数据类型(用于定义变量或类型):char double float int long short struct union void enum(枚举型) longlong signed unsigned
控制语句:break case continue default do else for goto if switch while return
存储类型:auto register extern static const
其他类型:
sizeof:求所占内存大小(单位是字节)
typedef:给已有类型取别名
volatile:防止编译器优化的
关于volatile的意义,根据标准C的定义、volatile的目的是,避免进行默认的优化处理.比如说对于编译器优化的功能,如果从编译器看来,有些多余的代码的话,编译器就会启动优化程序,并删除一些代码,但是这在嵌入式系统中很有可能是关键性的处理,必须不能保证被编译器删掉,所以提供了Volitile来声明,告诉编译器无论如何都不要删掉我。
Extern volatile int event_flag;
这样声明event_flag全局变量的话,就不用担心event_flag 被优化掉,程序将按照设计来运行。
10、赋值运算符(从右到左运算)
= 把=右边的值赋给=左边
num=8; 把8赋值给num
11、标准输出函数printf()
(1)引入头文件 #include <stdio.h>
(2)调用函数
参数1:字符串
printf("helloworld");//把字符串里面的内容原样显示在输出屏幕上
printf("字符串+格式化符",多个和格式化符一样多的参数)
int num = 8;
printf("num = %d",num);
12、存储方式
正数:以补码形式存储
正数的原码、补码、反码都一样
char ch =127; 0111 1111
负数:以补码形式存储,最高位是符号位,正数是0,负数是1,剩下的都是数据位
char ch = 129;
1000 0001 (补码)
1000 0000
1111 1111 -127
补码转为原码:
a.先减1,再取反(数据位)
b.先取反,再加1
char ch = 128;---->%d -128
1000 0000 (补码)
1111 1111
1000 0000 (-128的原码)
13、算术运算符
注:用移位运算符代替算术运算符,效率最高
A=b%m-----a=b&(m-1) a=b*2^n-----a=b<<n a=b/2^n------a=b>>n
a=b/8*8+b%4 -> a=((b>>3)<<3)+(b&3)
a=b*15 -> a=(b<<4)-b
+ - * / %
%----》两边的表达式只能是int 或者 char
5/2=2 int/int=int 5.0/2 = 2.500000 float/int = float--->float/float=float
隐式转换:范围小----》范围大
int + float = float
int + short = int
unsigned + signed = unsigned
float + double = double
unsigned a = 2;signed b = -5;
printf("%d",a+b);------>-3
0000 .... 0010 (a的原码)
1000.... 0101 (b的补码)
1111.... 1011 (b的原码) signed ----> unsigned
1111.... 1101 (a+b) unsigned---->signed
1000.... 0011
强制转换:(数据类型)变量名 (数据类型)(表达式)
float f =12.5;
(int)f; %d--->12
f; %f--->12.5 在强制转换过程中,变量本身并没有发生改变
++:如果放在变量名前,先自加后使用;放在变量名后,先使用后自加
++如果单独成句,没有区别
注:不要在同一行使用多个‘++’‘--’
三:C基础(2)
1. 常数如何描述
#define X 65
65
0x41
0101
'\101' ('\0' == 0)
2. 变量空间如何申请
(数据类型关键字: 1.要多大; 2. 如何使用此空间)
char
short
int
long
float
double
3. 如何表达运算
数学运算符(加减乘除)
+
-
*
/
==
%
示例: 求a的十位数(a/10%10)
位运算符(比特位操作)
~
<<
>>
逻辑右移---unsigned
算数右移---[signed] xx
左移---有符号和无符号一样
----这个算数右移才对
& (清楚某个bit位,保留必要字段) 掩码~(子网掩码)
清除掉a的bit n: a = a & ~(1<<n);
提取a的bit n: (a & (1<<n))>>n;
| 置位某个bit
将a的bit n变成1: a = a | (1<<n)
将a的bit n开始的三个bit设置成任意值x(0-7): a = a&~(7<<n) | (x<<n);-----当所要设置的三位数原来为111时,无论你想要设置为什么值‘|’后还为111,因此应先将这三位清0,再”|”,(想要修改连续2位时---3<<n清0,以此类推)
1〉作业:计算一个整数的二进制中1的个数(整数可为正为负)
int main()
{
int n=12;
int count=0,i=0;
while(i<=sizeof(int)*8)//int就是一个坑,不同系统字节不同
{
if(n&(1<<i))
count++;
i++;
}
printf("%d\n",count);
return 0;
}
//2
int main()
{
int num=12,i=0,j;
while(num)
{
num = num&(num-1);
i++;
}
printf("%d\n",i);
j=count_bits(num);
printf("%d\n",j);
return 0;
//3
include <stdio.h>
int main()
{
int a = 0xffffffff;
int bitn = 0,n=0;
//提取bit位
While(n<=sizeof(int)*8)//不同操作系统数据类型所占空间不同!!!!!!!!!!!!!!!!!!
{
If(a&(1<<n))
{
n++;
Bitn++;
}}
printf("bits: %d\n", bitn);
}
^(扫雷应用)
a = a^b;
b = a^b;
a = a^b;
逻辑运算符(真与假)
&&:int i=0,j=0;
If(i++ && j++); ---->i==1,j==0(逻辑判断第一个表达式逻辑为假,运行即中断)
||
!
?:
第二个#define定义的常量可读性更强
4. 内存值如何查看
Printf(“%d%d%d%d\n”,i++,++i,i++,i++);
1>逗号运算从右到左运算
2>i++先将i暂存在寄存器中然后自加,++i直接取加1后的值给i
1〉作业:编写一个猜数字的软件
int x = rand()%100;//随机获取100以内的数
int num;
printf("input a number:");
while(1)
{
getchar();
scanf("%d",&num);
if(num == x)
{
printf("right!\n");
break;
}
else if(num > x)
{
printf("too big:");
}
else
printf("too small:");
}
}
5.控制语句
1〉if要点
A:注意区分if(a=1)与if(a==1)
B:if语句中else总是与紧挨着的那个if配对,与书写格式的缩进无关,若要实行强制的配对,可用以下语句
If()
{if() 语句块1;}
Else 语句块2;
2〉作业:判断一年是否为闰年?
1:能被4整除但又不能被100整除
2:能被100整除又能被400整除
int main()
{
int year;
printf("please input a year number:");
while(1)
{
scanf("%d",&year);
if((year%4==0 && year%100!=0) || (year%100==0 && year%400==0))
{
printf("%d is a full year!\n",year);
break;
}
else
printf("%d is not a full year!please input a another year:",year);
printf("\n");
}
return 0;
3》switch语句
A:其表达式可以是整型 字符型 枚举型
B:default后的break可省略
4〉for语句
三个表达式都可以省略,但“;”不能省:注意省略的条件,当语句2省略时,如果循环中无goto,break,return则陷入死循环
5〉break只能用在循环语句和switch语句中
注:如何使用break跳出多层循环-------使用flag(看门狗设置0/1,再通过判断真假来跳出循环)
6〉*求素数的三种方法
一:for(i=2;i<=(n-1);i++)
if(n%i==0)i在2到n-1之间任取一个数,如果n能被整除则不是素数,否则就是素数
二:for(i=2;i<n/2;i++)
if(n%i==0) /*i在2到n/2之间任取一个数,如果n能被整除则不是素数,否则就是素数
三:for(i=2;i<(n=sqrt(n+i));i++)
if(n%i==0) /*i在2到sqrt(n)之间任取一个数,如果n能被整除则不是素数,否则就是素数,在下省了下面的输出步骤*/
/*在本程序中使用第三种方法来求解*/
#include <stdio.h>
#include <math.h>
int main(void)
{
int i; /*外循环*/
int j; /*内循环*/
int flag; /*素数标志,flag为1则此数为素数*/
flag = 0;
//int n;
i = 2;
while( i <= 100)
{
j = 2;
flag = 1; /*假设此数为素数*/
while(j <= (int) sqrt(float(i)))
{
if(0 == (i %j))
flag = 0; /*根据第三种算法可知次数不为素数*/
j ++;
}
if(flag)
printf("%d\t",i);
i++;
}
printf("\n");
return 0;
}
四:C基础(3)
一〉技术点:
1. 溢出越界
1〉、溢出:小容器装大东西
数据类型超过了计算机字长的界限而出现的数据溢出;
2〉、溢出可能原因:
当应用程序读取用户数据,复制到应用程序开辟的内存缓冲区中,却无法保证缓冲区的空间足够时 (假设定义数组int array[10], 而在调用时使用array[11] 或存放的数据超过int类型容量等), 内存缓冲区就可能会溢出.
越界:使用的东西超过了本身的范围
比如你定义的A[3][3],这是二维数组,意为三行三列,其中第一行的元素有A[0][0],A[0][1],A[0][2](第二三行依次类推)在后面你调用这个数组中的元素时,如果你调用A[0][3],这样就应该算越界了,也就是超过定义数组的范围了,因为这个数组第一行最多到A[0][2]
2. ++i, i++
Printf(“%d%d%d”,i,i++,++i);-----------(2,1,2)----将i++当作i先放着,把表达式计算完后再将值赋给i
函数:先将表达式的值计算好了再传给参给函数
3. atoi()
函数原型:int atoi(const char* nptr);
函数的用法:参数nptr字符串(且为数字字符串),如果第一个非空格字符存在,是数字或者正负号则开始做类型转换,之后检测到非数字(包括结束符 \0) 字符时停
止转换,返回整型数。否则,返回零。
4.十进制转十六进制:
1:先取低四位-------a&oxf 2:右移四位-----a>>4
二〉C语句
1.分支语句
1〉goto与longjmp
Goto-----短跳转语句(作用域限定---只在一个{}以内有作用)---在硬件驱动时应用
Longjmp----c长跳转语句
2〉switch语句
-------case后的表达式为整型或字符型,,必须有default(可不用放在最后,但最好放在最后)
输入输出语句:
3〉Scanf-------从键盘获取数据
对‘\n’敏感应与getchar()配对使用
‘*’---抑制符(scanf(“%*d%c”,&s,&a)-----第一个数据接收 scanf("%*d%d%*d",&a,&a,&a);
printf("%d\n",a);
)
4〉Gets()-------在如数组这样有界的数据操作时容易发生越界!!!!!!!!!!!!!
5〉Sscanf()-------可从字符串中获取想要的字符
Eg :char arr[]={“N: 100”}
Int x=0;
Sscanf(arr,”%*s%d”,&x);----从arr中提取100
Sscanf()与atoi()的联系
6〉例子:猜数字游戏------rand()获取随机数,但一般比较大,根据需要利用%/来获取数据
7〉Printf()-------必须加‘\n’,打印首先输出在缓冲区中,有‘\n’时数据直接刷出缓冲区并打印到显示器上
‘\t’----制表符(打印时以最优格式输出)
Eg:printf(“xxxxx\t1234\n”);
Printf(“xxxx\t123\n”);
8〉Puts()------专用打字符串,自带‘\n’
Eg:while(1){
Sleep(1);
Printf(“ .......\n”);//putchar(r);fflush(stdout);(刷出缓冲区)
}
Printf(“\rh\re\rl\rl\n”)------’\n’---回到行首
For(i=0;i<100;i++){
Printf(“/r%d”,i);
Fflush(stdout);
Sleep(1);
}------------数据每隔一秒显示在行首
注:printf()---------------------打印前/背景颜色----应用:将调试信息分级别(红--error黄--waring黑--right)
9〉Sizeof()--------运算符(求空间容量,编译器统计在编译阶段就获得)
10〉Strlen()--------一种算法(以0结束统计并结束)
Char a=”hello”;
Sizeof(a);-------6
Strlen(a);--------5;
Eg:void func(int arr[100])
{
Printf(“%d\n”,sizeof(arr));--------------4(int arr[100]--------地址(指针))
}
2.数据类型:
1〉enum----枚举(快速宏定义)-----依次为所列元素自动定为0,1.。。。
2〉void --------*:空指针
---------无:代表万能
3〉51c------sbit(bit型----资源有限)
----支持访问bit型,但无此数据类型,也无bool型,但有逻辑真假表示
4〉char:有符号字节变量
动作:越界------int a[4]={0,0,1,2,3};-------有危险
:溢出-------char c=128;(数据越界)----有误差
Char c=500;char a=500;------------编译时:就将一个常量500放在了不可改变的内存中
运行时:将500的备份分赋给c,a;
5〉字符串常量-------不能被修改也不能被优化
3.内存:
1〉常量--------放在只读区(本身就存在不可修改,可在a.out文件中修改你想要改变的输出内容),编译时已经存在
2〉变量-------运行时才出现,常量备份给他,临时存在,可改
3〉Static--------放在data区,若在全局变量前加此关键字,则该变量只能被本文件使用
-----------------1〉作用域限定(全局变量或函数内)2〉申请data静态数据存储区
4〉Const-----(符号常量,常变量)------伪存储类型关键字
Eg:const float g=9.8-------类似于将变量放在常量区
*((float*&g))= 10.1-----通过地址改值
Extern -----定义的变量可被其他文件使用
六:C基础(5)
1、二维数组
//定义一个长度为4的数组,数组里面的每个元素又是一个长度为3的int数组
int brr[4][3]; ----->数据类型:int [4][3]
brr[0] ~ brr[3] ----->数据类型:int [3]
brr[0][0] ~ brr[0][2] ----->数据类型:int
初始化:
int brr[4][3]={ {1,2,3},
{4,5,6},
{7,8,9},
{10,11,12}}
int brr[][3]={1,2,3,4,5,6,7,8,9,10,11,12};
int brr[4][3]={{1},{2}}; brr[0][0] = 1 brr[1][0]=2
int brr[4][3]={1,2,3,4,5,6,7};
输入输出:
int brr[][3]={1,2,3,4,5,6,7,8,9,10,11,12};
brr[0][0] -----%d printf("%d",brr[0][0]);
brr[0]:
for(j=0;j<3;j++)
{
printf("%d",brr[0][j]);
}
brr[1]:
for(j=0;j<3;j++)
{
printf("%d",brr[1][j]);
}
...
brr:
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
printf("%d",brr[i][j]);
}
}
2、字符数组
//定义一个长度为20的字符数组
char str[20];
char str[]={'h','e'};
char btr[20];
char str[20]={'h','e','l','l','o'};
char str[20]={"hello"};
char str[20]="hello"; sizeof(str)=20 strlen(str)=5;
字符串的特点:以'\0'作为结束标志
char str[]="hello"; sizeof(str)=6 strlen(str)=5
字符串的输入输出:
printf("%s",字符串的首地址); %s在输出的时候自动去寻找\0,遇到\0就输出结束
puts(字符串的首地址);//自动将\0转换成\n
gets(字符串的首地址);//遇到\n认为输入结束-------------容易发生越界,造成栈爆炸
scanf("%s",字符串的首地址);//遇到\n、空格、TAB键认为输入结束
Eg:char str[]=“ab\n\012\\\””;
Printf(“%d”,strlen(str));-------------输出6
转义字符:
3、跟字符串相关的函数
1〉strlen 计算字符串的长度
int len = strlen(字符串的首地址);----以\0作为结束标志
2〉strcpy 复制-------以字符串2的\0作为结束标志
EG:char str[]={‘h’,’e’};btr[20];----即当字符数组全部初始化且不含’\0’时,strlen结果不一定正确
Strcopy(btr,str);--------------结果可能有误(strlen以\0作为复制的结束标志而str中无’\0’)
strcpy(字符串1的首地址,字符串2的首地址);//将字符串2复制到字符串1里面去
//字符串1的空间必须足够大,返回值是字符串1的首地址
连缀调用:
strcpy(ctr,strcpy(btr,str));//将str复制给btr,又将btr复制给ctr
3〉strcat 链接
strcat(字符串1的首地址,字符串2的首地址);//将字符串2链接到字符串1后面去
//字符串1的空间必须足够大,返回值是字符串1的首地址
连缀调用
strcat(ctr,strcat(btr,str)); //将str链接到btr后面去,又将btr链接到ctr后面去
4〉strcmp 比较(ASCII码值)
"helloworld" "hellokitty"
strcmp(字符串1的首地址,字符串2的首地址);
int n = strcmp(str1,str2);
if(n>0)printf("str1>str2");
else if(n<0)printf("str1<str2");
else printf("str1=str2");
自己实现以上函数:
5.重点练习
1〉strcpy()-------注意,当完成元素复制后,在目标串的最后,人为加上’\0’
2>strcat()--------------------最后手动加上\0
3〉strlen()----------以\0结束
3>Strcmp
4〉Int型数组中的次大值
Strlen()------以\0结束
Strlen(str1)不一定为5,strlen(str2)也不一定为5;(找\0)
Sizeof(str1)=sizeof(str2)=5 strlen(str3)=strlen(str4)=6
部分初始化输入字符--strlen()结果正确
全部初始化输入字符---strlen 结果不一定正确
5〉打印ab对称图形
int main()
{
int i,j,k,m,c;
char ch='A';
printf("input your lines:");
scanf("%d",&m);
for(i=0;i<m;i++)
{
for(k=1;k<m-i;k++)
{
printf(" ");
}
for(c=i;c>=0;c--)
{
printf("%c",ch+c);
}
for(j=1;j<=i;j++)
{
printf("%c",ch+j);
}
printf("\n");
}
}
6〉二维字符数组排序
#include <stdio.h>
#include <string.h>
int main()
{
char a[5][20]={"apple","banana","orange","pineapple","watermelon"};
int i,j;
char s[20]={‘\n’};
//通过比较大小排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1-i;j++)
{
if(strcmp(a[j],a[j+1])>0)
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
//通过比较长度排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1-i;j++)
{
if(strlen(a[j]>strlen[j+1]))
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
return 0;
}
7〉寻找字符串中出现次数最多的字符
#include <stdio.h>
int main()
{
int count=0,max=0,index=-1;//count 记录每个字符出现的次数,max出现次数最多的字符次数,index次数最多字符的下标
char a[]="helloworld";
int i=0,j=0;
for(i=0;a[i]!='\0';i++)
{
for(j=0;a[j]!='\0';j++)//查找每个字符出现的次数
{
count=0;
if(a[i]==a[j])
count++;
if(count > max)
{
max=count;
index=i;
}
}
}
}
8〉字符串转换为int-----------已知int为正
#include <stdio.h>
int main()
{
char a[]="1234"
int i,sum=0;
for(i=0;str[i]!=0;i++)
{
sum = sum*10+str[i]-'0';
}
printf("%s",sum);
}
9〉int(有正有负)转换为char
#include <stdio.h>
int main()
{
int i=0,num;
int flag=0;
char a[20]={'\0'};
printf("input a int num:");
scanf("%d",&num);
if(0 == num)
{
a[i++]='0';
}
if(0>num)
{
num=-num;
flag=1;
}
while(num>0)
{
a[i++] = num%10+'0';
num /= 10;
}
if(flag)
{
a[i++] = '-';
}
int len=strlen(a);
for(i=0;i<len/2;i++)
{
int temp = a[i];
a[i] = a[len-1-i];
a[len-1-i] = temp;
}
printf("%s",a);
return 0;
}
10〉查找特定字符
七:C基础(6)
一〉一维数组:
定义 数据类型 数组名[数组长度]
int arr[5];//定义了一个长度为5的int 数组 sizeof(arr)=int [5]=20
二〉二维数组
定义 数据类型 数组名[数组长度]
//定义一个长度为3的数组,数组里面每个元素又是一个长度为4的Int数组
int brr[3][4]; ------>sizeof(brr)=int [3][4]
brr[0] ~ brr[2];------>sizeof(brr[0])=int [4]
brr[0][0] ~ brr[2][3];----->sizeof(brr[0][0])=int
brr == &brr[0]
brr[0] == &brr[0][0]
三〉一维字符数组:
//定义一个长度为20的char数组
char str[20];
char str[20]={'a','b','c'}; sizeof(str)=20 strlen(str)=3
char str1[]={'a','b','c'}; sizeof(str1)=3 strlen(str1)=?
char str2[]="abc"; sizeof(str2)=4 strlen(str2)=3
输入输出:%s
printf("%s",字符串的首地址); printf("%s",str);
%s在输出的时候会自动去寻找\0,遇到\0就打印结束
scanf("%s",字符串的首地址); scanf("%s",str);
%s在输入的时候遇到空格、回车、TAB键就认为输入结束
四〉二维字符数组:
//定义一个长度为5的数组,数组里面每个元素又是一个长度为20的char数组
char str[5][20];
char str[5][20]={{"apple"},{"banana"},{"orange"},{"pineapple"},{"watermelon"}};
输入输出:%s
For(i=0;i<5;i++)
{
Scanf(“%s”,str[i]);
Printf(“%s”,str[i]);
}
//按照字符串的大小将其从小到大排序
//按照字符串的长度将其从小到大排序
int main()
{
char a[5][20]={"apple","banana","orange","pineapple","watermelon"};
int i,j;
char s[20]={‘\n’};
//通过比较大小排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1;j++)
{
if(strcmp(a[j],a[j+1])>0)
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
//通过比较长度排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1;j++)
{
if(strlen(a[j]>strlen[j+1]))
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
return 0;
五〉什么是指针
1.指针的定义
指针是一种数据类型,用来保存地址的数据类型
地址:计算机内存单元的编号
2、什么是指针变量
用来保存地址的变量,指针变量的值就是地址
数据类型 * 指针变量名
“*”:代表我们定义了一个指针
数据类型:该指针变量所指向的变量的数据类型
int * p;//p是一个指针变量,p指向了一个Int变量,p的值是一个int变量的地址
char *s; ----->s的数据类型:char *
在32位操作系统下,所有的数据类型的指针都占4个字节(sizeof(int))
3、指针的初始化
int i = 5;
int * p;
p = &i; //p指向i
int i =5;
int *p = &i;
int i=5,*p=&i;
!!!在使用指针之前,必须进行初始化
4、指针的访问
通过取值运算符*
前提:int i=5,*p=&i; *p实质上就是i这片内存空间,就是i的一个别名,操作*p就是在操作i
int *a;
*a = 52; //这里的指针变量a是一个野指针
int *p = NULL; //p是一个空指针
!!!操作空指针和野指针都是不合法的
5、*在C语言中的三种用法
(1)乘法
(2)定义指针变量 int *p;
(3)取值运算符 *p;
如果*号前面有数据类型,是在定义指针变量;如果没有,就是在取值
6、指针的运算
指针的运算实质上是地址的运算
1〉算术运算
p+n/p-n:p向地址增大(减小)的方向移动n个数据
具体移动的字节跟指针指向的数据类型有关 sizeof(数据类型)*n
p++:p向地址增大的方向移动1个数据
int i = 5, j =10;
int *p = &i;
int *q = &j;
p-q:两个指针之间相隔元素的个数(p、q必须是同类型的指针)
int arr[5] = {1,2,3,4,5};
int *p = arr;
int *q = &arr[4];
printf("%d",q-p); 4
注意:
同类型的指针不可以进行相加、相乘、相除
2〉关系运算
> < >= <= == !=
两个指针必须是同类型的,而且必须指向同一数据区域才可以进行关系运算
指针s q指向同一数据区域
指针可以和0进行比较,判断指针是否为空
7.指针与一维数组
int arr[5] = {1,2,3,4,5};
int *p = arr;//指针变量P指向了数组的首元素
p = &arr[0] =arr
p+1 = &arr[1] =arr+1
p+2 = &arr[2] = arr+2 ....
!!!*p = *&arr[0] = arr[0] = *arr =p[0]
*(p+1)= *&arr[1] = arr[1] =*(arr+1) =p[1]
*(p+2)= *&arr[2] = arr[2] =*(arr+2) =p[2]
*(p+3)= *&arr[3] = arr[3] =*(arr+3) =p[3]
*(p+4)= *&arr[4] = arr[4] =*(arr+4) =p[4]
注意:arr++ ----->error
arr是个地址常量,p是个变量,所以数组名在运算中可以作为指针参与运算,但不可以被赋值
*(s+1)!!!!!!!!!!!违法操作
*s++----------*(s++)---先将s++表达式的值得出再取值
六〉作业
D对
A对-----常量区不能被修改
D对-----------将p(一个未知地址)的值传给了s,但后来字符数组的首地址又给了s,所以最后没有对p所指向的地址操作,FUN函数没有返回值,子函数执行完就被销毁,因此为P所指向的地址空间随机
八:C基础(七)
一〉计算机内存分布:
二〉二级指针
int i = 5;
int *p = &i; //p的数据类型:(int *) *p的数据类型:int
int **pI = &p; //pi的数据类型:(int **) *pi的数据类型:(int *) **pi的数据类型:int
*p = i = 5;
*pi = p = &i; //*pi就是p的一个别名,操作*pi就是在操作p
**pi = *p = i = 5; //**pi是i的别名,操作**pi就是在操作i
1.指针与二维数组
int arr[2][3]= {1,2,3,4,5,6};
//定义一个指针指向数组中的第一个int元素
int *p = &arr[0][0] = arr[0];
p = &arr[0][0] = arr[0]
p+1 = &arr[0][1]
p+2 = &arr[0][2]
p+3 = &arr[1][0]
p+4 = &arr[1][1]
p+5 = &arr[1][2]
*p = *&arr[0][0] = arr[0][0] = *arr[0]
*(p+1) = *&arr[0][1] = arr[0][1] = *(arr[0]+1)
*(p+2) = *&arr[0][2] = arr[0][2] = *(arr[0]+2)
*(p+3) = *&arr[1][0] = arr[1][0] = *(arr[0]+3)
*(p+4) = *&arr[1][1] = arr[1][1] = *(arr[0]+4)
*(p+5) = *&arr[1][2] = arr[1][2] = *(arr[0]+5)
for(i=0;i<6;i++)
{
printf("%d",*(p+i));
}
int arr[2][3]= {1,2,3,4,5,6};
//定义一个指针指向二维数组的首元素,此时首元素名称:a[0]---a[2],数据类型:int [3]
数据类型 * 变量名
数组指针--(指向二维数组其数据类型为int [3]):int (*p)[3]; //[]的优先级比*高,所以*p必须要括起来
sizeof(p) = 4
p = &arr[0] = arr;
p+1 = &arr[1] = arr+1
*p = *&arr[0] = arr[0] = &arr[0][0] = *arr //*p是一个地址
*(p+1) = *&arr[1] = arr[1] = &arr[1][0] = *(arr+1)
**p = *(&arr[0][0]) = arr[0][0] = **arr = p[0][0]
**(p+1) = *&arr[1][0] = arr[1][0] = **(arr+1) =p[1][0]
arr[0][1] = *&arr[0][1] = *(&arr[0][0]+1) = *(*p+1)
arr[0][2] = *&arr[0][2] = *(&arr[0][0]+2) = *(*p+2)
arr[1][1] = *&arr[1][1] = *(&arr[1][0]+1) = *(*(p+1)+1)
arr[1][2] = *&arr[1][2] = *(&arr[1][0]+2) = *(*(p+1)+2)
arr可以看成是一个二级指针
int arr[5] = {1,2,3,4,5};
int * p = &arr[0] = arr; //定义一个指针指向数组中的首元素
int (*p1)[5] = &arr; //定义一个指针指向整个数组
2.指针数组:
int *p[2]; //定义了一个长度为2的数组,数组的元素都是一个指向int的指针
sizeof(p) = 8
int m = 5;
int n = 10;
p[0] = &m;
p[1] = &n;
p = &p[0]
*p = *&p[0] = p[0] = &m
**p = *p[0] = *&m = 5
*(p+1) = p[1] = &n
**(p+1) = *p[1] = *&n = 10
3.字符指针
char str[20] = "helloworld";
char *pc = str;
char *pc1 = "helloworld"; //字符串常量本身就是字符串的首地址
(1)scanf("%s",str); ok
scanf("%s",pc1); error 不可以对常量区的内容进行修改
(2)printf("%s",str); ok
printf("%s",pc1); ok
(3)str[1] = *(pc+1)
*(pc+1) = 's'; ok
*(pc1+1) ='s'; error 不可以对常量区的内容进行修改
(4)char *pc1 = "helloworld"; ok
char str[20];
str = "helloworld"; error str是一个地址常量
注:常量只可被读,不能修改
三〉函数
(1)函数的作用:使我们的程序变得更加模块化,同时可复用性更强
(2)函数的分类
库函数:
1)先引入头文件
2)调用函数
如果函数有返回值,变量 = 函数名(实际参数1,实际参数2...)
#include <stdio.h>
printf("字符串",实际参数2,实际参数3...)
自定义函数:
1)函数声明 //告诉计算机有这个函数
返回值类型 函数名(形式参数1,形式参数2...);
//形式参数必须要写数据类型,变量名可省略,句末一定要有分号,返回值如果没有写void
2)函数定义
返回值类型 函数名(形式参数1,形式参数2...)
{
函数体;
return 变量名; //如果没有返回值,该句话可省略
}
//函数定义的时候形式参数的变量名一定不能省
3)函数调用
变量 = 函数名(实际参数1,实际参数2...)
调用子函数结束,给子函数分配的这片空间就被销毁
在调用子函数之前,如果该子函数已经定义,那么可以不写函数声明
如果该子函数的定义在调用子函数之后,那么必须写函数声明
全局变量:定义在函数体外部的变量 作用域:自定义开始到文件结束
局部变量:定义在函数体内部的变量 作用域:自定义开始到最近的}结束
四〉gdb调试工具
(1)编译的时候添加参数 -g
gcc -g cal.c -o cal
(2)进入gdb
gdb cal
(3)设置断点
b main //在main函数处设置断点
b 30 //在第30行处设置断点
(4)r(run) 运行
(5)n(next) ---->不进入子函数
(6)s(step) ---->进入子函数
(7)q(quit) ----->退出
(8)回车代表执行上一个命令
五〉static
修饰局部变量:如果该变量没有被初始化,那么就被初始化为0;如果已经被初始化,那么就只能被初始化一次
修饰全局变量:该变量只能在本.c文件使用
修饰函数:该函数只能在本.c文件使用
static修饰全局变量
static修饰函数
隐藏,只允许在本文件中调用,不允许在其他文件文件中调用
static修饰局部变量(增长变量的生命周期);
首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。
六〉作业:
用子函数实现两个数的交换
void change(int *a,int *b)
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
int main()
{
int m,n;
m=1;
n=2;
printf("m=%d n=%d\n",m,n);
change(&m,&n);
printf("m=%d n=%d\n",m,n);
return 0;
}
九:C基础(8)
一〉结构体
1. 定义:
构造一个新的数据类型
struct person{
char name[20];
int height;
};
该数据类型叫 struct person
typedef struct person per;
typedef struct person{
char name[20]; //成员变量之间要用分号隔开,成员变量的数据类型可以相同也可以不同
int height;
}per;
初始化:per p1={"lijianfei",175};
访问结构体成员变量:结构体变量名.成员变量名
输出:printf("%s %d\n",p1.name,p1.height);
输入:scanf("%s%d",p1.name,&p1.height);
//定义一个指针指向p1
per * pper;
pper = &p1;
*pper <====> p1
(*pper).name (*pper).height
//通过结构体指针访问成员变量
指针变量名->成员变量名
pper->name
pper->height
//定义一个结构体变量p2
per p2;
p2 = p1; //将p1的值赋值给p2
p2.name p2.height
2、字节对齐(32OS gcc编译器)
系统一次性分配的字节数是成员变量里面最大的字节对齐数
3、共同体
union union{
char ch;
int i;
};
注意:共同体所占内存空间取决于成员变量中最大的内存空间 sizeof(union un) = 4
共同体中所有成员变量的首地址都是一致的,所以在某一时刻只能取一个成员变量使用
//定义一个共同体变量
union un u1;
4、大小端
大端序:低字节存高地址处,高字节存低地址处
小端序:低字节存低地址处,高字节存高地址处
判断计算机是大端序还是小端序:(通过共同体)
u1.i = 0x12345678;
if(u1.ch == 0x78)
printf("小端序\n");
else
printf("大端序\n");
5、Const
const 数据类型 变量名; //该变量只读
const int a = 10;
a = 20; //error a只读
const char *p = "helloworld";
char str[20] = "helloworld";
const char *p = str; //<====>char const *p = str;
*p = 'e'; --->error str这片空间只读
char * const p = "hello";
p就只能指向“hello”这个字符串,不能再指向其他字符串
const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的安全性和可靠性。另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。另外CONST在其他编程语言中也有出现,如C++、PHP5、C#.net、HC08C。
3、指针函数:返回值是指针的函数就是指针函数
LINUX C
一:SHELL基础3
一〉嵌入式系统3
二〉Linux软件管理机制3
1. dpkg-----3
2.apt_get-3
3.apt-cache-3
三〉APT软件包管理器3
四〉LINUX系统结构4
五〉SHELL命令5
六〉通配符6
七〉输入输出重定向6
八〉命令置换7
九〉进程管理7
十〉linux文件系统8
1.文件系统类型8
2.SCSI(机械硬盘)与IDE8
3.根目录文件9
4.文件类型10
5.创建链接文件:10
6.文件压缩与解压10
二:shell脚本编程基础11
一〉编写流程11
二〉:变量11
1.自定义变量11
2.位置参数与预定义变量11
3.环境变量12
三〉shell程序和语句12
1.语句12
1〉说明性语句13
2〉功能性语句13
3〉结构性语句15
四〉shell函数21
1.定义21
2.传参:21
三:c高级23
一〉引入23
二〉数组24
1:一维数组24
2:二维数组--按行存放24
三〉指针24
1:值访问25
2:运算25
3:一维数组与指针25
4.指针与二维数组26
5.指针数组27
6字符指针数组27
7:多级指针28
8:const/void指针28
四〉函数29
1.函数定义:29
2.函数声明:29
3.函数传参30
1〉复制传参30
2〉地址传递30
3〉全局变量31
4.指针函数31
5.函数指针32
六〉递归函数34
七〉GCC编译器35
1.编译运行步骤35
2.GNU工具35
3.定义-交叉平台编译器35
4.主要组件35
八〉GDB(用途小36
九〉结构体**36
1.结构体数组37
1〉定义struct stu a[3];37
2〉初始化38
3〉提取元素38
2.结构体指针38
3.结构体指针数组38
十>内存分配***39
1.存储模型39
1>变量39
2.动态分配39
十一〉makefile基本结构39
1. 工作原理40
2.基本格式40
一:SHELL基础
一〉嵌入式系统
X86 arm---体系架构
MIT---麻省理工
Ubuntu----”人道待人”理念
艾伦.图灵---计算机之父
Richard staliman-----自由软件之父(GNU运动(软件开源,免费)----gcc.gdb.gedit)---->GNU/Linux(在GNU运动下开发的LINUX系统)
嵌入式应用:无人驾驶----利用声呐不断测试与障碍物的距离来控制车速
二〉Linux软件管理机制
三个配置文件:
软件源配置文件(软件仓库):/etc/apt/sources.list
本地软件包索引文件(可下载的目录):/var/lib/apt/lists
本地文件下载缓存目录:/var/cache/apt/archives
- dpkg------
完成本地软件包安装管理(依赖关系明确)
注:在/var/cache/apt/archives(本地缓存目录---安装包存放的地方)下输入命令
命令:sudo dpkg -i <package(完整的安装包文件名--就在上面的那个目录下可以查看)>:安装软件
Sudo dpkg -P <package>:移除已经安装的软件包及配置文件
2.apt_get---管理下载文件
步骤:1:查找软件最新版本 2:配置文件依赖关系 3:下载 4:安装
Sudo apt-get install (-d) packg------下载并安装(不安装)
Sudo apt-get remove/clean/update/upgread/check(卸载/删除已下载的包文件/下载更新软件包信息列表(包括更新软件源里的软件信息)/升级到最新版本/查看系统中依赖关系的完整性) [-d/--purge/--reinstall/-v/-f] (仅下载不安装/与remove连用完全卸载(包括软件包与文件)/重新安装/获取版本号/修复依赖关系)packg
3.apt-cache---查询软件相关信息
Apt-cache show/search/policy/depend(获取二进制软件包的详细信息/检索软件包/获取安装状态/获取依赖关系)
三〉APT软件包管理器
---1:检查修复软件包依赖关系 2:利用网络主动获取软件包
deb软件包(ubuntu系统):二进制软件包(deb)--可直接安装 源码包(deb-src)--需解压再安装
rehat系统:rpm软件包
四〉LINUX系统结构
- Shell是一个命令编译器,将用户命令编译成二进制程序,交给操作系统执行。【 F】??
- 在默认情况下,所定义的Shell变量的作用域是局部有效。【 F】
- 使用DHCP服务配置动态IP的过程,就犹如一个租借过程。【T 】
linux内核含有硬件驱动控制硬件,硬件做出相应的反应来控制shell,shell再将信息反馈给用户
SHELL---命令行解释器(更快更直接)
当前使用版本--bash(bourn again shell)<------sh(bourn shell)的增强版
五〉SHELL命令
Sudo shoutdown -h n/now--关机
Ctrl+c---取消关机
Sudo shoutdown -r n/now---重启==reboot(直接执行boot-loder(系统引导程序))
命令---指令 选项 参数
Ls -l DS/----显示DS目录下的内容
多命令在一行同时执行-----命令1;命令2..(ls;pwd)
一个命令在多行------命令.........
\命令.....
Tab---命令补齐
(两次tab)----显示当前目录下具有相同前缀的名称
Less/more -----分页显示
查询历史命令:history n(默认500行)
设置历史命令容纳量:HISTSIZE =m
Echo $HISTSIZE----查看
基本系统维护命令
Passwd---修改密码(root 可修改其他用户的(su))
Cd /home/----用户主目录
Export----查看环境变量----可以修改其中的环境变量(su -m)
Echo----显示指令(当有多个空格时只打印一个(认为其为一个指令))
Echo “ ”---显示字符串
Echo $PATH--查看当前编译路径
???Mips--:交叉编译
Date--查看当前时间
While(1)
{
System(“date”);
Sleep(1);
}//每秒打印一次时间
??????Date -s “%y-%m-%d”
**********df--查看磁盘空间使用率(tmpfs--虚拟内存空间:1G的虚拟内存可虚拟出4G的内存空间)
Df -a-----显示所有的文件系统使用情况(包括proc,sysfs虚拟内存)
Df -ah--以M为单位显示
Du----显示每个文件/目录所占磁盘块数(每个磁盘占512个字节)
/etc/passwd 文件----用户清单(p86)
/etc/group 文件-----组与成员列表(p89)
Adduser <用户名>----创建用户
************/etc/skel目录----被/etc/sbin/adduser使用,将新用户想要的配置文件拷贝到/etc/skel中
Usermod---修改用户属性(推出登陆root用户)
sudo usermod -l newname oldname(修改用户名)
sudo usermod -d /home/user1(全新目录) -m(将家目录搬到新目录下,与-d一起使用) -l newname oldname --------------------(修改用户名并修改家/主目录))
Sudo deluser name----仅仅删除用户名,相关文件还存在
Sudo deluser --remove-home user1-----删除用户并删除用户目录
/etc/adduser.conf---- 用户配置文件
Sudo delgroup groupname---删除组
Exit----退出用户
*********************************
六〉通配符
1〉‘*’---匹配任意长度的字符串(file_*.txt)
’?’----匹配一个长度的字符
‘[]’---匹配其中指定的一个字符(file_[ot].txt==file_o.txt,file_t.txt)
‘[ - ]’-------指定的一个字符范围([a-z])
‘[^ ]’-----除了其指定的字符
管道:‘|’-----第一个命令的输出作为第二个命令的输入
Eg:ls /usr/bin | wc -w-----统计指定目录下的文件数目
七〉输入输出重定向
1〉‘〉file’---覆盖输入重定向
2〉‘〉〉file’----追加输入重定向
3〉‘〈file’---覆盖输出重定向
4〉‘<<file’---追加输出重定向
’2>file’-----错误覆盖输出重定向
‘2>>file’----错误追加重定向
Eg:ls 2.c 2> e.c
Char * fgets(char *s,int size,FILE *stream);
Fgets(str,10,stdin)----从缓冲区获取指定长度的字符(stdin(标准输入) stdout(标准输出))
流;标准输入流-------》文件描述符 0
标准输出流 1
标准错误流 2
八〉命令置换
命令1 `命令2`------将命令2(esc键下的但引号)的结果作为命令1 的参数
Eg:ls `pwd`
九〉进程管理
程序==数据结构+算法 静态
进程:程序的一次执行
命令:
Ps -au ---〉仅显示当前用户的进程详细信息
%cpu---cpu占用率 %MEM---内存占用率 VSZ--虚拟文件使用字节数 RSS---占用磁盘字节数 TTY---正在使用的配置文件 STAT--状态 START---运行时间
Ps -aux ---->显示所有用户进程信息
Top ----实时监控进程: NI----进程优先级 PR---进程控制块
???????Nice -----调整进程优先级
KILL PID-----终止进程==ctrl+c(向内核发送KILL9)(强制终止进程)
进程状态
Z---将死态(没运行,但占一部分空间) L不重要
‘+’----进程挂起
十〉linux文件系统
1.文件系统类型
df查看磁盘空间
磁盘文件系统:
网络文件系统:NFS(文件系统)---系统移植应用
专有/虚拟文件系统
2.SCSI(机械硬盘)与IDE
固态读写快,作为系统盘15秒开机了解一下。240g再储存点常用软件和网游绰绰有余了。
机械读写慢,但可以作为储存文档,电影等数据之类的硬盘,相对于固态也更安全,更稳定。如果固态的容量不够可以考虑再加一个机械。如果240g就够用的话也没必要再加机械。
内存----内存条(执行程序时的变量等)--断电重启后数据不在
外存----a.out存在磁盘空间---断电重启后数据还在
IDE--固定硬盘
Sata---机械硬盘
交换分区----交换分区(了解)(将内存内容写到磁盘,或从内存读出)
3.根目录文件
/(linux文件系统根目录) /bin(存放系统中最常用的可执行文件(二进制文件))
/boot(存放Linux内核和系统启动文件) /dev(设备文件)
/etc(配置文件,用户信息文件等) /home(用户主目录)
/lib(存放共享的库文件) /mnt(存放被挂载文件的挂载点----可用于文件共享)
/proc(存放所有标志为文件的进程) /root(超级用户主目录) /var(存放长度可变的文件)
Linux与windows区别
EXT4---LINNX现在最新文件格式 FAT64--windows常用文件格式
最大区别:(换行符区别)LINUX---\n windows---\r\-n
4.文件类型
命令:
File <name>---查看文件类型
Cp 目标 被复制 -r ----------------复制目录
Mv day2/ ~ ---移动到家目录
Mkdir -p mm/kk/ll
LINUX不会显示二进制内容 cat a.out---结果是乱码
Head -n name tail -n name-----显示头尾指定行数
5.创建链接文件:
硬链接:利用linux分配的物理编号--inode建立链接-----不能跨越文件系统---不可恢复
软链接:利用文件的路径名建立链接(相对路径)--可恢复(重新创建一个同名的link-name链接又会重新启动)
ln [-s(软链接)] target link-name(改变target的内容Link-name的内容会相应的改变)
6.文件压缩与解压
归档文件(.tar):将一组文件或目录保存在一个文件中---使占用磁盘空间增大
压缩文件(.gz):将一组文件或目录保存在一个文件中,并以某种存储格式存储在磁盘空间上,内存总和比所有文件之和小
1〉Gzip工具:有链接文件不能被压缩打包(windows无链接文件)
Gzip -d/-l/-num(1-9)(解压/查看压缩文件内的信息/指定压缩比率(默认6),数字越大压缩力度越大) name
Gunzip [-f] (提示已经有的同名文件)name-----解压
2〉Tar命令(归档文件):[-c] tarname filename
Tar -cf 123.tar 1.c 2.c 3.c ---->tar -xvf 123.tar 创建一个新的归档文件
Tar -xfv 123.tar -----解压并显示指定归档文件
Gzip -d 123.tar --->解压==gunzip
二:shell脚本编程基础
运维师与外挂
shell区分大小写
一〉编写流程:#!/bin/bash(当前使用的脚本类型,执行该文件的程序)--开头一行(!虽然注释掉了但系统可以阅读)-----------〉编写程序并保存退出----〉给文件设置执行权限(chmod 权限 文件名)-----〉./x.sh(运行程序)
二〉:变量
1.自定义变量(默认为全局变量)
变量名=值
取用变量值:$变量名6g
Num=20
Unset num
2.位置参数与预定义变量
c语言中:int main(int argc ,char *argv[])命令行参数
$?-返回调用函数的返回值
3.环境变量
$HOME--引用
PATH(默认路径,执行shell脚本时可以快速找到):---shell可执行的路径(将x.sh放在其路径下,不用指定其路径(x.sh直接运行))
执行程序必须知道其存放路径:./x.sh
/bin-----存放基本的指令(二进制可执行程序)
DATE=`date`----命令置换 LIST=`list`
Unset---取消环境变量,在命令行输入:unset z
Set---设置环境变量
三〉shell程序和语句
1.语句
比较---条件测试语句
1〉说明性语句
2〉功能性语句
Read----阻塞功能,被read赋值的变量不允许再次被赋值,read 可被回车终止
Read var1 var2 var3
注:运算符左右两侧必须加空格
‘*’----通配符,利用‘\’去除二义性
$num=9---$命令行提示符
I++------->$i=`expr $i + 1`(x) 对:i=`expr $i + 1`
test==[ x ]
$?(上一条命令的结果)------0为真,非0为假
Z--zero n--no
eq==等 ne==not eq gt==big than ge==big eq lt==last than le==last eq
text测试时“=”两边必须有空格
-d(目录文件) -f(普通文件)重要
整数测试时-ge等表达式, 前后都是需要数字类型的变量或者常量, 一般都是${xxx} 不用加双引号
3〉结构性语句
分支语句
注:条件(test) ’[]‘里面最左边与最右边必须有空格
-a(逻辑与) -o(逻辑或) !(逻辑非)
If [ 条件 ]
Then
Elif [ 条件 ]
Then
Else
fi
Let 指令--取十位 ‘|’将多个项合并
循环语句
实现1-100的和 将当前目录下的所有文件拷贝到上一级目录
‘*’可打印出当前路径下的所有文件名
仅仅打印当前路径
创建文件 :$1$i--文件名,从键盘输入file 3
删除文件:命令行输入file 1 3
if [ $# -eq 3 ]
then
count=$3
else
echo input error
exit
fi
i=$2//1
while [ $i -le $count ]
do
rm $1$i # file1 file2 file3
let i++
done
循环控制语句
第一次$output为空
作业:用shell打印9*9乘法表
Echo (默认换行) 参数选项: -n 输出文字不换行
-e 将转义符跟后边的特殊字符解释成特殊意义
-E 不解释转义字符
1〉#!/bin/bash
For i in {1..9}
Do
Foe j in {1..9}//error----{1..$i}
Do
If [ $j -le $i ]
Then
Let sum=$i*$j
Echo -ne “$j*$i=$sum\t”//\t----水平制表符
Fi
Done
Echo
Done
2〉
for ((i=1;i<=9;i++))
{
for ((j=1;j<=$i;j++))
{
let sum=$i*$j
echo -ne "$j*$i=$sum\t"
}
echo " "
}
3〉
\t----水平制表符
四〉shell函数
1.定义
2.传参:
‘..’传给$1 “-aux”传给$2
实现两个数相加($?获取上一程序的状态)
abc为全局变量123 456
设置局部变量:local 变量名
打印出123 123
三:c高级
一个寄存器只有十多个字节。定义寄存器变量时,也存放在栈区
一〉引入
判断寄存器存储变量与AUTO变量执行速度
Time(&sttar)---以秒统计时间
For(;j<=N;j++);
Time(&stop);
Printf(“%d\n”,stop-start);
Time_t t;time(&t);//将从1970.1.1到当前时间的秒数赋给变量t,
printf(“today’s time and date is %s”,ctime(&t));------打印出当前日期与时间(ctime(&t)将秒数转换为日期与时间)
二〉数组
1:一维数组
Int n=10;int arr[n];(对)
Int n=10;int arr[n]={1,2,3,4};(错)---n为可变值
初始化时,才被分配空间
gcc编译不能查看数组越界
str后面存放str1打印结果---hellohaa
2:二维数组--按行存放
Arr=&arr[0]
Arr[0]=&arr[0][0]
因为arr[0]与arr[0][0]的地址重合因此打印出的地址相同,但是*(arr)=&arr[0][0]为一个地址,而*(&arr[0][0])=arr[0][0]--为一个值
三〉指针
地址--内存单元的编号
此时野指针并没有被使用因此不会报错
空指针 ---物理--0地址
---逻辑-不会指向任何地方(与野指针相对)
Int *p=NULL<==>int *p=0;(0为NULL的编号)vi /user/lib/gcc/.....(宏定义地址)
1:值访问
Int n=20;int *p=&n;
Int *p = (int *)100;(强制转换)对---
1〉直接访问:n=20 2>间接访问:*p=20-----寄存器只能间接访问
‘*’-----解引用符
2:运算----实质是地址的偏移
1>两个指针之间不能进行‘+’ 2〉倒叙字符串
3〉数据类型不匹配,无法获取想要的数据,将返回0
3:一维数组与指针
a为地址常量,只读,a++错
1〉求最小值
4.指针与二维数组
二维数组元素名,为行地址
数组指针--〉行指针只能指向二维数组---int (*p)[3]=a//[二维数组的每个元素里有多少个数据]
p[i] <-->*(p+i)-----*/ []:降维作用
P[i][j]----1:将p[i]看作一个整体将其解引用得(*(p+i))[j]-----将[j]先解引用*(p[i]+j)-----将两个都解引用*(*(p+i)+j)
5.指针数组
Int *a3[2]-----[二维数组元素个数]
a2,a4所存内容一样,为同一片内存空间,只是行列数划分不同,但对其操作不会越界
A2[2][3]; 1 2 3/4 5 6/
A4[3][2]:1 2/3 4/5 6/
6字符指针数组---存放的为字符指针常量的首地址,不能被修改
Char *str[5]:指针访问常量区,字符串 常量 char str1[]:字符串变量
printf(“%c”,**y);---h y++--->段错误
7:多级指针
二级指针--指针的地址
&(char *)
打印出world 打印出e
P+1------地址偏移4个字节,因为其中存的字符串地址占四个字节
二级指针与二维Int数组
Int **p=b----p指向a[0]
*p+1---第一行再移一个
8:const/void指针
1〉Const---修饰一个变量为只读
Eg:strcat(char *dest,const char *src)
Strcat(dest,”http”);
修饰指针:
1〉
Int const *p=&n;//*p不能修改
指针数据类型与所指对象的数据类型要相同
2〉void 指针
Void *p=&a;
引用:*(int *)p
---可指向任意数据类型--但因无确定的数据类型,无法知道取多少空间里的数据,因此需要强制转换
四〉函数
1.函数定义:完成某些特定功能的代码模块。形参名不可省
2.函数声明:若函数定义写在main函数之后,就必须写. 形参名可省
Eg:int add(int ,int ); int add(int a,int b);
注:个代码程序,有且仅有一个main函数
3.函数传参
1〉复制传参
实参并没发生交换
2〉地址传递
Swap(&x,&y)
仅仅将p q里面的内容传给了子函数,而p q地址不变----------相当于复制传递
实现了两个实参值的交换
传递函数:一维整型数组,字符数组传参,二维数组
地址传参:int (*a)[3] int a[][3]--复制传参 但两者都是地址
3〉全局变量---定义在所有函数之外
Int flag;
Func(flag)
static变量与全局变量不做初始化,初始化默认为0----放在静态变量数据区
Eg:
N--二维数组行 m----二维数组列
4.指针函数----返回值为地址
Eg:
p--变量的值,str3----地址
函数可以返回一个值:p可以返回,并由p存储的地址里面的内容依然存在,而str3能返回,但其内容已经被销毁,因此不能返回一个局部变量的地址
当static修饰时,可以返回str里面的内容
Static:(变量存放在静态存储区)
一:修饰局部变量----增长了变量的生命周期
二:修饰函数:限制函数的作用域,只能在当前文件中被调用
三:修饰全局变量:限制变量作用域,只能在本文件中使用
static可由程序员手动放入堆区,没有运行的代码放入代码段中
5.函数指针==函数名
定义:存放函数地址的指针
函数返回值类型 (*指针名)(函数参数类型)
指针指向函数:函数名就为函数的起始地址
q==add-->add[10,20]==q[20][20];
Char * (*p)(char *,char*)
小应用:float decall(float (*fp)(int),int n)//float (*fp)()函数指针
{
float s;
s=(*fp)(n);//调用函数指针
return s;
}
五〉函数指针数组
调用:
六〉递归函数(做题)
1〉自己调用自己 2〉寻找递归终止条件
先递推再回归
例子:5!
七〉GCC编译器(GNU CC)
1.编译运行步骤
1: .c ----->.i 2: .i--〉.s 3: .s-->.o
.so/----动态库 ./a静态库 ----------cd /lib
2.GNU工具
3.定义-交叉平台编译器
4.主要组件
分析器:将源语言程序代码转换为汇编语言
汇编器:将汇编语言代码转换为CPU可执行字节代码(二进制文件)
链接器:将汇编器生成的单独目标文件组合成可执行的应用程序
标准C库:标准的C函数都由C库提供
生成汇编文件----〉检查语法错误
八〉GDB(用途小)---数组越界
----printf()代替,查看错误 printf行缓存函数---当输出内容占满一行才输出,因此需利用’\n’来结束一行的缓存
九〉结构体***
---数据结构的链表使用
结构体对齐标准:最长字节对齐方式(编译器不同对齐不同),GCC是4字节对齐方式
1.结构体数组
1〉定义struct stu a[3];
2〉初始化
3〉提取元素
4:结构体调用结构体
-----调用
2.结构体指针
1:定义 2:调用
3.结构体指针数组
十>内存分配***
1.存储模型
1>变量
全局变量与局部变量---若两个变量名相同,在局部就对局部变量进行操作
具有外部链接的静态 :外部链接,所有函数之外
具有内部链接的静态 :内部链接(static),所有函数之外
空链接的静态 :局部变量+static
2.动态分配-----heap(堆区)
----应为malloc返回为void *因此需强制转换为与p的数据类型相同的空间
Free()---仅仅需要释放空间的首地址
十一〉makefile基本结构
----------工程管理器
1.工作原理
make工程管理器根据( 文件时间戳 )来自动发现更新过的文件从而减少编译的工作量。
2.基本格式
避免头文件重复定义
sunq为可执行程序
$@ $^:所有的依赖文件
C基础
一:linux基础 3
1、Linux常用命令 4
2、Vim编辑器 6
二:C基础 6
1、计算机的组成 6
2、计算机的数据表示 8
3、C补习内容 8
4、LinuxC的开发流程 8
5、程序的入口:main()函数 9
6、变量 9
7、基本数据类型(32位操作系统) 9
三:C基础(2) 12
1. 常数如何描述 12
1〉作业:计算一个整数的二进制中1的个数(整数可为正为负) 14
4. 内存值如何查看 16
1〉作业:编写一个猜数字的软件 16
5.控制语句 17
1〉if要点 17
2〉作业:判断一年是否为闰年? 17
3》switch语句 18
四:C基础(3) 19
一〉技术点: 19
1. 溢出越界 19
2. ++i, i++ 19
3. atoi() 20
4.十进制转十六进制: 20
二〉C语句 20
1.分支语句 20
1〉goto与longjmp 20
2〉switch语句 21
3〉Scanf-------从键盘获取数据 21
2.数据类型: 22
1〉enum----枚举 22
2〉void 22
3〉51c------sbit 22
4〉char: 22
5〉字符串常量 22
3.内存: 23
1〉常量 23
2〉变量 23
3〉Static 23
4〉Const 23
六:C基础(5) 23
1、二维数组 23
2、 字符数组 25
3、跟字符串相关的函数 26
1〉strlen 26
2〉strcpy 26
3〉strcat 26
4〉strcmp 26
1〉strcpy()-- 27
2> strcat()--- 27
3〉strlen()- 28
3> Strcmp 29
4〉Int型数组中的次大值 29
5〉打印ab对称图形 30
6〉二维字符数组排序 31
7〉寻找字符串中出现次数最多的字符 32
8〉字符串转换为int-----------已知int为正 33
9〉int(有正有负)转换为char 34
10〉查找特定字符 35
七:C基础(6) 35
一〉一维数组: 35
二〉二维数组 36
三〉一维字符数组: 36
四〉二维字符数组: 36
五〉什么是指针 38
1.指针的定义 38
2、什么是指针变量 38
3、指针的初始化 39
4、指针的访问 39
5、*在C语言中的三种用法 40
6、指针的运算 40
1〉算术运算 40
2〉关系运算 40
7.指针与一维数组 41
六〉作业 42
八:C基础(七) 44
一〉计算机内存分布: 44
二〉二级指针 44
1.指针与二维数组 45
2.指针数组: 46
3.字符指针 47
三〉函数 48
四〉gdb调试工具 49
五〉static 50
六〉作业: 50
九:C基础(8) 51
一〉结构体 51
1. 定义: 51
2、字节对齐 52
3、共同体 52
4、大小端 53
5、 Const 53
4、指针函数: 54
一:linux基础
什么是嵌入式:软件控制的硬件
嵌入式---一个定制的计算机
所以:硬件和软件需要根据设备要实现的功能专门去设计
也就是说嵌入式系统所需要的操作系统是可以被修改的
linux系统是一个开源软件--可以免费得到源代码并且可以自由修改
学习软件:
1、VNC (同屏) server viewr
2、飞秋
3、VM(虚拟机) 虚拟的一台电脑,可以在这台虚拟的电脑上运行linux操作系统
4、ubuntu
LinuxOS windows
ubuntu windowxp
redhat window7
红旗 window10
ubuntu每半年更新一次 04 10
每两年更新一个长期版本(稳定)LST
Linux是一个开源的、多用户的、多任务的操作系统,要求必须以用户和密码去登录
shell:命令行解释器 用户和内核进行沟通的桥梁
shell其实就是程序,程序提供给我们一个界面(终端),这个界面可以让我们输入命令 (shell命令)
1、Linux常用命令
ctrl+alt+t:打开一个终端
命令行提示符-------》 用户名@计算机名:当前路径$
$:代表当前登录的用户是一个普通用户
#:超级用户,root用户,权限最高
su - 用户名:切换到该用户
ctrl+d:从超级用户切换回普通用户
pwd:查看当前路径
sudo:增加权限
绝对路径:从根目录开始的路径
相对路径:具体看参照物
windows的文件系统犹如一片森林,各自独立
Linux的文件系统犹如一颗倒置的树,所有的目录都在跟目录之下
ls:查看当前目录下的内容
ls 目录路径:查看该目录下的内容
ls -a:查看当前路径下的所有内容(包括隐藏文件 以.开头的文件叫隐藏文件)
ls -l :以长格的形式显示当前目录下内容的详细信息
drwxrwxrwx 6 linux linux 4096 Jun 9 20:14 A9Server
d:文件类型
linux下文件分为7种:
- --------->普通文件
d ---------->文件夹
p ----------->管道文件
l ----------->链接文件
b ------------>块设备文件
c ------------>字符设备文件
s ------------->套接字文件
cd:切换目录路径
cd .. :退回上一级目录
cd ../..:退回上一级目录的上一级目录
cd -:返回上一次的目录路径
cd .:返回当前目录
cd ~(cd):快速返回家目录
ctrl+shift+'+':放大字体
ctrl + '-':缩小字体
安装中文:ibus-setup
ctrl+空格:语言切换
clear(ctrl+l):清屏
touch 文件名:创建一个文件(文件名可以多跟)
rm 文件名:删除一个文件
mkdir 文件夹名:创建一个文件夹
mkdir -p :连续创建多级目录
rmdir 文件夹名:删除一个文件夹(只能删除空文件夹)
rm -rf 文件夹名:删除一个文件夹
cp 被复制的文件名 目标路径:
cp -r 被复制的文件夹名 目标路径
cp -i 被复制的文件名 目标路径:提示是否被覆盖
mv 被移动的文件 目标路径:
mv 1.c 2.c ------>2.c不存在则把1.c改名为2.c 存在则先改名然后覆盖
mv day1 day2 ----->day2不存在改名,存在移动
cat 文件名:查看该文件的内容(一般适用于比较短的)
more 文件名:查看该文件的内容(一般适用于比较长的)
按回车:一行一行的向下查看
按q退出
sudo reboot:重启
sudo shutdown -h now:立即关机
sudo shutdown -h 20:20分钟后关机
chmod 777 文件名:把该文件的权限全都打开
Tab:自动补全
向上的箭头:上一次的命令
ctrl+c:结束当前进程
2、Vim编辑器
vim 文件名:如果文件时存在的就直接打开,如果不存在新建该文件再打开
vim的三种模式:命令行模式、插入模式、底行模式
刚打开一个文件是命令行模式,命令行模式---》插入模式(按i) 插入模式---》命令行模式(esc) 命令行模式---》底行模式(shift+:)
命令行模式:
i:从光标所在地方的前面开始插入
I:从光标所在的行首开始插入
a:从光标的下一个字符的前面开始插入
A:从光标所在行的行末开始插入
o:从光标所在的下一行(新建的行)开始插入
O:从光标所在的上一行(新建的行)开始插入
插入模式:在插入模式下才可以编辑文本
底行模式:(以:开始)
:w 保存
:q 退出
:wq 保存并退出 :x ZZ(命令行模式下)
:wq! 强制保存退出
:wq 文件名 以新名字保存的备份文件
:set nu 设置行号
:set nonu 取消行号
:set hlsearch 设置高亮
:range %s/str1/str2/g 在range范围内所有的str1都替换成str2
/str (命令行模式) 查找str
nyy:n代表行数(命令行模式下进行复制粘贴)
p:粘贴
ndd:剪切
u:撤销
=gg (命令行模式下)自动调整格式
gcc编译器,gcc 2.c会默认生成可执行文件a.out,执行 :./a.out
gcc 2.c -o 2将可执行文件a.out改名为2,执行:./2
3.6 文本内容的删除操作;
x 一个字符;
#x 删除几个字符,#表示数字,比如3x;
dw 删除一个单词;
#dw 删除几个单词,#用数字表示,比如3dw表示删除三个单词;
dd 删除一行;
#dd 删除多个行,#代表数字,比如3dd 表示删除光标行及光标的下两行;
d$ 删除光标到行尾的内容;
J 清除光标所处的行与上一行之间的空格,把光标行和上一行接在一起;
二:C基础
1、计算机的组成
硬件
CPU:运算器、控制器(控制从内存获取数据,与内存交换数据很快)、寄存器
存储器:
内部:ROM(只读存储器) RAM(随机存储器,断电后数据易丢失)
外部:硬盘、U盘
输入设备:键盘、鼠标、麦克风
输出设备:显示器、音响、打印机
软件
系统软件:windows linux UNIX
应用软件: wps qq
一台没有任何软件的计算机称为“裸机”。
储存1T是指硬盘的总容量为1TB。太字节(Terabyte),计算机存储容量单位,也常用TB来表示。1TB=1024GB==2^40字节
2、计算机的数据表示
数值数据 非数值数据
数值数据:二进制 十进制 八进制(以0作为前缀,0~7) 十六进制(以0x作为前缀,0~f(F))
十进制转其他进制:除2/8/16倒取余
非数值数据:‘a’ '\n' '5'
3、C补习内容
(1)数据类型
基本数据类型:int float char
复合数据类型:数组、指针、函数、结构体
(2)运算符
(3)结构性语句
顺序语句
选择语句
循环语句
(4)算法
求最大值 冒泡排序
4、LinuxC的开发流程
输入一个数,求这个数是奇数还是偶数
(1)分析建模
num
num%2==0---->偶数
num%2==1---->奇数
(2)画流程图
a.输入一个数num
b.如果num%2==0,输出该数是偶数
c.如果num%2==1,输出该数是奇数
(3)翻译成C代码
(4)编译
(5)运行
5、程序的入口:main()函数
int main()
{
return 0;
}
6、变量
在程序运行过程中其值可以改变的量
7、基本数据类型(32位操作系统)
int (4个字节) [signed]int:-2^31 ~ 2^31-1 unsigned int:0 ~ 2^32-1
short (2个字节)[signed]short:-2^15 ~ 2^15-1 unsigned short:0 ~ 2^16-1
long (4个字节)
long long (8个字节)
float:4个字节
double:8个字节
char:1个字节 [signed]char:-128~127 unsigned char :0~255
看成是一个字节的int
列子:int a=’\101’;//0101;//0x41;//65
Float 1.4;//1.4=14*10-1
(浮点数存储:左边为符号 中间整数存储 右边指数存储)
指数存储占低8位,符号位占高八位
8、标识符的定义(变量名、数组名、函数名)
a.由数字、字母、下划线组成
b.首字母不能是数字
c.不能与关键字重名
d.尽量见名知意
9、关键字
关键字:32个 由系统定义的 全都是小写
数据类型(用于定义变量或类型):char double float int long short struct union void enum(枚举型) longlong signed unsigned
控制语句:break case continue default do else for goto if switch while return
存储类型:auto register extern static const
其他类型:
sizeof:求所占内存大小(单位是字节)
typedef:给已有类型取别名
volatile:防止编译器优化的
关于volatile的意义,根据标准C的定义、volatile的目的是,避免进行默认的优化处理.比如说对于编译器优化的功能,如果从编译器看来,有些多余的代码的话,编译器就会启动优化程序,并删除一些代码,但是这在嵌入式系统中很有可能是关键性的处理,必须不能保证被编译器删掉,所以提供了Volitile来声明,告诉编译器无论如何都不要删掉我。
Extern volatile int event_flag;
这样声明event_flag全局变量的话,就不用担心event_flag 被优化掉,程序将按照设计来运行。
10、赋值运算符(从右到左运算)
= 把=右边的值赋给=左边
num=8; 把8赋值给num
11、标准输出函数printf()
(1)引入头文件 #include <stdio.h>
(2)调用函数
参数1:字符串
printf("helloworld");//把字符串里面的内容原样显示在输出屏幕上
printf("字符串+格式化符",多个和格式化符一样多的参数)
int num = 8;
printf("num = %d",num);
12、存储方式
正数:以补码形式存储
正数的原码、补码、反码都一样
char ch =127; 0111 1111
负数:以补码形式存储,最高位是符号位,正数是0,负数是1,剩下的都是数据位
char ch = 129;
1000 0001 (补码)
1000 0000
1111 1111 -127
补码转为原码:
a.先减1,再取反(数据位)
b.先取反,再加1
char ch = 128;---->%d -128
1000 0000 (补码)
1111 1111
1000 0000 (-128的原码)
13、算术运算符
注:用移位运算符代替算术运算符,效率最高
A=b%m-----a=b&(m-1) a=b*2^n-----a=b<<n a=b/2^n------a=b>>n
a=b/8*8+b%4 -> a=((b>>3)<<3)+(b&3)
a=b*15 -> a=(b<<4)-b
+ - * / %
%----》两边的表达式只能是int 或者 char
5/2=2 int/int=int 5.0/2 = 2.500000 float/int = float--->float/float=float
隐式转换:范围小----》范围大
int + float = float
int + short = int
unsigned + signed = unsigned
float + double = double
unsigned a = 2;signed b = -5;
printf("%d",a+b);------>-3
0000 .... 0010 (a的原码)
1000.... 0101 (b的补码)
1111.... 1011 (b的原码) signed ----> unsigned
1111.... 1101 (a+b) unsigned---->signed
1000.... 0011
强制转换:(数据类型)变量名 (数据类型)(表达式)
float f =12.5;
(int)f; %d--->12
f; %f--->12.5 在强制转换过程中,变量本身并没有发生改变
++:如果放在变量名前,先自加后使用;放在变量名后,先使用后自加
++如果单独成句,没有区别
注:不要在同一行使用多个‘++’‘--’
三:C基础(2)
1. 常数如何描述
#define X 65
65
0x41
0101
'\101' ('\0' == 0)
2. 变量空间如何申请
(数据类型关键字: 1.要多大; 2. 如何使用此空间)
char
short
int
long
float
double
3. 如何表达运算
数学运算符(加减乘除)
+
-
*
/
==
%
示例: 求a的十位数(a/10%10)
位运算符(比特位操作)
~
<<
>>
逻辑右移---unsigned
算数右移---[signed] xx
左移---有符号和无符号一样
----这个算数右移才对
& (清楚某个bit位,保留必要字段) 掩码~(子网掩码)
清除掉a的bit n: a = a & ~(1<<n);
提取a的bit n: (a & (1<<n))>>n;
| 置位某个bit
将a的bit n变成1: a = a | (1<<n)
将a的bit n开始的三个bit设置成任意值x(0-7): a = a&~(7<<n) | (x<<n);-----当所要设置的三位数原来为111时,无论你想要设置为什么值‘|’后还为111,因此应先将这三位清0,再”|”,(想要修改连续2位时---3<<n清0,以此类推)
1〉作业:计算一个整数的二进制中1的个数(整数可为正为负)
int main()
{
int n=12;
int count=0,i=0;
while(i<=sizeof(int)*8)//int就是一个坑,不同系统字节不同
{
if(n&(1<<i))
count++;
i++;
}
printf("%d\n",count);
return 0;
}
//2
int main()
{
int num=12,i=0,j;
while(num)
{
num = num&(num-1);
i++;
}
printf("%d\n",i);
j=count_bits(num);
printf("%d\n",j);
return 0;
//3
include <stdio.h>
int main()
{
int a = 0xffffffff;
int bitn = 0,n=0;
//提取bit位
While(n<=sizeof(int)*8)//不同操作系统数据类型所占空间不同!!!!!!!!!!!!!!!!!!
{
If(a&(1<<n))
{
n++;
Bitn++;
}}
printf("bits: %d\n", bitn);
}
^(扫雷应用)
a = a^b;
b = a^b;
a = a^b;
逻辑运算符(真与假)
&&:int i=0,j=0;
If(i++ && j++); ---->i==1,j==0(逻辑判断第一个表达式逻辑为假,运行即中断)
||
!
?:
第二个#define定义的常量可读性更强
4. 内存值如何查看
Printf(“%d%d%d%d\n”,i++,++i,i++,i++);
1>逗号运算从右到左运算
2>i++先将i暂存在寄存器中然后自加,++i直接取加1后的值给i
1〉作业:编写一个猜数字的软件
int x = rand()%100;//随机获取100以内的数
int num;
printf("input a number:");
while(1)
{
getchar();
scanf("%d",&num);
if(num == x)
{
printf("right!\n");
break;
}
else if(num > x)
{
printf("too big:");
}
else
printf("too small:");
}
}
5.控制语句
1〉if要点
A:注意区分if(a=1)与if(a==1)
B:if语句中else总是与紧挨着的那个if配对,与书写格式的缩进无关,若要实行强制的配对,可用以下语句
If()
{if() 语句块1;}
Else 语句块2;
2〉作业:判断一年是否为闰年?
1:能被4整除但又不能被100整除
2:能被100整除又能被400整除
int main()
{
int year;
printf("please input a year number:");
while(1)
{
scanf("%d",&year);
if((year%4==0 && year%100!=0) || (year%100==0 && year%400==0))
{
printf("%d is a full year!\n",year);
break;
}
else
printf("%d is not a full year!please input a another year:",year);
printf("\n");
}
return 0;
3》switch语句
A:其表达式可以是整型 字符型 枚举型
B:default后的break可省略
4〉for语句
三个表达式都可以省略,但“;”不能省:注意省略的条件,当语句2省略时,如果循环中无goto,break,return则陷入死循环
5〉break只能用在循环语句和switch语句中
注:如何使用break跳出多层循环-------使用flag(看门狗设置0/1,再通过判断真假来跳出循环)
6〉*求素数的三种方法
一:for(i=2;i<=(n-1);i++)
if(n%i==0)i在2到n-1之间任取一个数,如果n能被整除则不是素数,否则就是素数
二:for(i=2;i<n/2;i++)
if(n%i==0) /*i在2到n/2之间任取一个数,如果n能被整除则不是素数,否则就是素数
三:for(i=2;i<(n=sqrt(n+i));i++)
if(n%i==0) /*i在2到sqrt(n)之间任取一个数,如果n能被整除则不是素数,否则就是素数,在下省了下面的输出步骤*/
/*在本程序中使用第三种方法来求解*/
#include <stdio.h>
#include <math.h>
int main(void)
{
int i; /*外循环*/
int j; /*内循环*/
int flag; /*素数标志,flag为1则此数为素数*/
flag = 0;
//int n;
i = 2;
while( i <= 100)
{
j = 2;
flag = 1; /*假设此数为素数*/
while(j <= (int) sqrt(float(i)))
{
if(0 == (i %j))
flag = 0; /*根据第三种算法可知次数不为素数*/
j ++;
}
if(flag)
printf("%d\t",i);
i++;
}
printf("\n");
return 0;
}
四:C基础(3)
一〉技术点:
1. 溢出越界
1〉、溢出:小容器装大东西
数据类型超过了计算机字长的界限而出现的数据溢出;
2〉、溢出可能原因:
当应用程序读取用户数据,复制到应用程序开辟的内存缓冲区中,却无法保证缓冲区的空间足够时 (假设定义数组int array[10], 而在调用时使用array[11] 或存放的数据超过int类型容量等), 内存缓冲区就可能会溢出.
越界:使用的东西超过了本身的范围
比如你定义的A[3][3],这是二维数组,意为三行三列,其中第一行的元素有A[0][0],A[0][1],A[0][2](第二三行依次类推)在后面你调用这个数组中的元素时,如果你调用A[0][3],这样就应该算越界了,也就是超过定义数组的范围了,因为这个数组第一行最多到A[0][2]
2. ++i, i++
Printf(“%d%d%d”,i,i++,++i);-----------(2,1,2)----将i++当作i先放着,把表达式计算完后再将值赋给i
函数:先将表达式的值计算好了再传给参给函数
3. atoi()
函数原型:int atoi(const char* nptr);
函数的用法:参数nptr字符串(且为数字字符串),如果第一个非空格字符存在,是数字或者正负号则开始做类型转换,之后检测到非数字(包括结束符 \0) 字符时停
止转换,返回整型数。否则,返回零。
4.十进制转十六进制:
1:先取低四位-------a&oxf 2:右移四位-----a>>4
二〉C语句
1.分支语句
1〉goto与longjmp
Goto-----短跳转语句(作用域限定---只在一个{}以内有作用)---在硬件驱动时应用
Longjmp----c长跳转语句
2〉switch语句
-------case后的表达式为整型或字符型,,必须有default(可不用放在最后,但最好放在最后)
输入输出语句:
3〉Scanf-------从键盘获取数据
对‘\n’敏感应与getchar()配对使用
‘*’---抑制符(scanf(“%*d%c”,&s,&a)-----第一个数据接收 scanf("%*d%d%*d",&a,&a,&a);
printf("%d\n",a);
)
4〉Gets()-------在如数组这样有界的数据操作时容易发生越界!!!!!!!!!!!!!
5〉Sscanf()-------可从字符串中获取想要的字符
Eg :char arr[]={“N: 100”}
Int x=0;
Sscanf(arr,”%*s%d”,&x);----从arr中提取100
Sscanf()与atoi()的联系
6〉例子:猜数字游戏------rand()获取随机数,但一般比较大,根据需要利用%/来获取数据
7〉Printf()-------必须加‘\n’,打印首先输出在缓冲区中,有‘\n’时数据直接刷出缓冲区并打印到显示器上
‘\t’----制表符(打印时以最优格式输出)
Eg:printf(“xxxxx\t1234\n”);
Printf(“xxxx\t123\n”);
8〉Puts()------专用打字符串,自带‘\n’
Eg:while(1){
Sleep(1);
Printf(“ .......\n”);//putchar(r);fflush(stdout);(刷出缓冲区)
}
Printf(“\rh\re\rl\rl\n”)------’\n’---回到行首
For(i=0;i<100;i++){
Printf(“/r%d”,i);
Fflush(stdout);
Sleep(1);
}------------数据每隔一秒显示在行首
注:printf()---------------------打印前/背景颜色----应用:将调试信息分级别(红--error黄--waring黑--right)
9〉Sizeof()--------运算符(求空间容量,编译器统计在编译阶段就获得)
10〉Strlen()--------一种算法(以0结束统计并结束)
Char a=”hello”;
Sizeof(a);-------6
Strlen(a);--------5;
Eg:void func(int arr[100])
{
Printf(“%d\n”,sizeof(arr));--------------4(int arr[100]--------地址(指针))
}
2.数据类型:
1〉enum----枚举(快速宏定义)-----依次为所列元素自动定为0,1.。。。
2〉void --------*:空指针
---------无:代表万能
3〉51c------sbit(bit型----资源有限)
----支持访问bit型,但无此数据类型,也无bool型,但有逻辑真假表示
4〉char:有符号字节变量
动作:越界------int a[4]={0,0,1,2,3};-------有危险
:溢出-------char c=128;(数据越界)----有误差
Char c=500;char a=500;------------编译时:就将一个常量500放在了不可改变的内存中
运行时:将500的备份分赋给c,a;
5〉字符串常量-------不能被修改也不能被优化
3.内存:
1〉常量--------放在只读区(本身就存在不可修改,可在a.out文件中修改你想要改变的输出内容),编译时已经存在
2〉变量-------运行时才出现,常量备份给他,临时存在,可改
3〉Static--------放在data区,若在全局变量前加此关键字,则该变量只能被本文件使用
-----------------1〉作用域限定(全局变量或函数内)2〉申请data静态数据存储区
4〉Const-----(符号常量,常变量)------伪存储类型关键字
Eg:const float g=9.8-------类似于将变量放在常量区
*((float*&g))= 10.1-----通过地址改值
Extern -----定义的变量可被其他文件使用
六:C基础(5)
1、二维数组
//定义一个长度为4的数组,数组里面的每个元素又是一个长度为3的int数组
int brr[4][3]; ----->数据类型:int [4][3]
brr[0] ~ brr[3] ----->数据类型:int [3]
brr[0][0] ~ brr[0][2] ----->数据类型:int
初始化:
int brr[4][3]={ {1,2,3},
{4,5,6},
{7,8,9},
{10,11,12}}
int brr[][3]={1,2,3,4,5,6,7,8,9,10,11,12};
int brr[4][3]={{1},{2}}; brr[0][0] = 1 brr[1][0]=2
int brr[4][3]={1,2,3,4,5,6,7};
输入输出:
int brr[][3]={1,2,3,4,5,6,7,8,9,10,11,12};
brr[0][0] -----%d printf("%d",brr[0][0]);
brr[0]:
for(j=0;j<3;j++)
{
printf("%d",brr[0][j]);
}
brr[1]:
for(j=0;j<3;j++)
{
printf("%d",brr[1][j]);
}
...
brr:
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
printf("%d",brr[i][j]);
}
}
2、字符数组
//定义一个长度为20的字符数组
char str[20];
char str[]={'h','e'};
char btr[20];
char str[20]={'h','e','l','l','o'};
char str[20]={"hello"};
char str[20]="hello"; sizeof(str)=20 strlen(str)=5;
字符串的特点:以'\0'作为结束标志
char str[]="hello"; sizeof(str)=6 strlen(str)=5
字符串的输入输出:
printf("%s",字符串的首地址); %s在输出的时候自动去寻找\0,遇到\0就输出结束
puts(字符串的首地址);//自动将\0转换成\n
gets(字符串的首地址);//遇到\n认为输入结束-------------容易发生越界,造成栈爆炸
scanf("%s",字符串的首地址);//遇到\n、空格、TAB键认为输入结束
Eg:char str[]=“ab\n\012\\\””;
Printf(“%d”,strlen(str));-------------输出6
转义字符:
3、跟字符串相关的函数
1〉strlen 计算字符串的长度
int len = strlen(字符串的首地址);----以\0作为结束标志
2〉strcpy 复制-------以字符串2的\0作为结束标志
EG:char str[]={‘h’,’e’};btr[20];----即当字符数组全部初始化且不含’\0’时,strlen结果不一定正确
Strcopy(btr,str);--------------结果可能有误(strlen以\0作为复制的结束标志而str中无’\0’)
strcpy(字符串1的首地址,字符串2的首地址);//将字符串2复制到字符串1里面去
//字符串1的空间必须足够大,返回值是字符串1的首地址
连缀调用:
strcpy(ctr,strcpy(btr,str));//将str复制给btr,又将btr复制给ctr
3〉strcat 链接
strcat(字符串1的首地址,字符串2的首地址);//将字符串2链接到字符串1后面去
//字符串1的空间必须足够大,返回值是字符串1的首地址
连缀调用
strcat(ctr,strcat(btr,str)); //将str链接到btr后面去,又将btr链接到ctr后面去
4〉strcmp 比较(ASCII码值)
"helloworld" "hellokitty"
strcmp(字符串1的首地址,字符串2的首地址);
int n = strcmp(str1,str2);
if(n>0)printf("str1>str2");
else if(n<0)printf("str1<str2");
else printf("str1=str2");
自己实现以上函数:
5.重点练习
1〉strcpy()-------注意,当完成元素复制后,在目标串的最后,人为加上’\0’
2>strcat()--------------------最后手动加上\0
3〉strlen()----------以\0结束
3>Strcmp
4〉Int型数组中的次大值
Strlen()------以\0结束
Strlen(str1)不一定为5,strlen(str2)也不一定为5;(找\0)
Sizeof(str1)=sizeof(str2)=5 strlen(str3)=strlen(str4)=6
部分初始化输入字符--strlen()结果正确
全部初始化输入字符---strlen 结果不一定正确
5〉打印ab对称图形
int main()
{
int i,j,k,m,c;
char ch='A';
printf("input your lines:");
scanf("%d",&m);
for(i=0;i<m;i++)
{
for(k=1;k<m-i;k++)
{
printf(" ");
}
for(c=i;c>=0;c--)
{
printf("%c",ch+c);
}
for(j=1;j<=i;j++)
{
printf("%c",ch+j);
}
printf("\n");
}
}
6〉二维字符数组排序
#include <stdio.h>
#include <string.h>
int main()
{
char a[5][20]={"apple","banana","orange","pineapple","watermelon"};
int i,j;
char s[20]={‘\n’};
//通过比较大小排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1-i;j++)
{
if(strcmp(a[j],a[j+1])>0)
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
//通过比较长度排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1-i;j++)
{
if(strlen(a[j]>strlen[j+1]))
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
return 0;
}
7〉寻找字符串中出现次数最多的字符
#include <stdio.h>
int main()
{
int count=0,max=0,index=-1;//count 记录每个字符出现的次数,max出现次数最多的字符次数,index次数最多字符的下标
char a[]="helloworld";
int i=0,j=0;
for(i=0;a[i]!='\0';i++)
{
for(j=0;a[j]!='\0';j++)//查找每个字符出现的次数
{
count=0;
if(a[i]==a[j])
count++;
if(count > max)
{
max=count;
index=i;
}
}
}
}
8〉字符串转换为int-----------已知int为正
#include <stdio.h>
int main()
{
char a[]="1234"
int i,sum=0;
for(i=0;str[i]!=0;i++)
{
sum = sum*10+str[i]-'0';
}
printf("%s",sum);
}
9〉int(有正有负)转换为char
#include <stdio.h>
int main()
{
int i=0,num;
int flag=0;
char a[20]={'\0'};
printf("input a int num:");
scanf("%d",&num);
if(0 == num)
{
a[i++]='0';
}
if(0>num)
{
num=-num;
flag=1;
}
while(num>0)
{
a[i++] = num%10+'0';
num /= 10;
}
if(flag)
{
a[i++] = '-';
}
int len=strlen(a);
for(i=0;i<len/2;i++)
{
int temp = a[i];
a[i] = a[len-1-i];
a[len-1-i] = temp;
}
printf("%s",a);
return 0;
}
10〉查找特定字符
七:C基础(6)
一〉一维数组:
定义 数据类型 数组名[数组长度]
int arr[5];//定义了一个长度为5的int 数组 sizeof(arr)=int [5]=20
二〉二维数组
定义 数据类型 数组名[数组长度]
//定义一个长度为3的数组,数组里面每个元素又是一个长度为4的Int数组
int brr[3][4]; ------>sizeof(brr)=int [3][4]
brr[0] ~ brr[2];------>sizeof(brr[0])=int [4]
brr[0][0] ~ brr[2][3];----->sizeof(brr[0][0])=int
brr == &brr[0]
brr[0] == &brr[0][0]
三〉一维字符数组:
//定义一个长度为20的char数组
char str[20];
char str[20]={'a','b','c'}; sizeof(str)=20 strlen(str)=3
char str1[]={'a','b','c'}; sizeof(str1)=3 strlen(str1)=?
char str2[]="abc"; sizeof(str2)=4 strlen(str2)=3
输入输出:%s
printf("%s",字符串的首地址); printf("%s",str);
%s在输出的时候会自动去寻找\0,遇到\0就打印结束
scanf("%s",字符串的首地址); scanf("%s",str);
%s在输入的时候遇到空格、回车、TAB键就认为输入结束
四〉二维字符数组:
//定义一个长度为5的数组,数组里面每个元素又是一个长度为20的char数组
char str[5][20];
char str[5][20]={{"apple"},{"banana"},{"orange"},{"pineapple"},{"watermelon"}};
输入输出:%s
For(i=0;i<5;i++)
{
Scanf(“%s”,str[i]);
Printf(“%s”,str[i]);
}
//按照字符串的大小将其从小到大排序
//按照字符串的长度将其从小到大排序
int main()
{
char a[5][20]={"apple","banana","orange","pineapple","watermelon"};
int i,j;
char s[20]={‘\n’};
//通过比较大小排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1;j++)
{
if(strcmp(a[j],a[j+1])>0)
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
//通过比较长度排序
for(i=0;i<4;i++)
{
for(j=0;j<4-1;j++)
{
if(strlen(a[j]>strlen[j+1]))
{
strcpy(s,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],s);
}
}
}
for(i=0;i<5;i++)
{
printf("%s ",a[i]);
}
printf("\n");
return 0;
五〉什么是指针
1.指针的定义
指针是一种数据类型,用来保存地址的数据类型
地址:计算机内存单元的编号
2、什么是指针变量
用来保存地址的变量,指针变量的值就是地址
数据类型 * 指针变量名
“*”:代表我们定义了一个指针
数据类型:该指针变量所指向的变量的数据类型
int * p;//p是一个指针变量,p指向了一个Int变量,p的值是一个int变量的地址
char *s; ----->s的数据类型:char *
在32位操作系统下,所有的数据类型的指针都占4个字节(sizeof(int))
3、指针的初始化
int i = 5;
int * p;
p = &i; //p指向i
int i =5;
int *p = &i;
int i=5,*p=&i;
!!!在使用指针之前,必须进行初始化
4、指针的访问
通过取值运算符*
前提:int i=5,*p=&i; *p实质上就是i这片内存空间,就是i的一个别名,操作*p就是在操作i
int *a;
*a = 52; //这里的指针变量a是一个野指针
int *p = NULL; //p是一个空指针
!!!操作空指针和野指针都是不合法的
5、*在C语言中的三种用法
(1)乘法
(2)定义指针变量 int *p;
(3)取值运算符 *p;
如果*号前面有数据类型,是在定义指针变量;如果没有,就是在取值
6、指针的运算
指针的运算实质上是地址的运算
1〉算术运算
p+n/p-n:p向地址增大(减小)的方向移动n个数据
具体移动的字节跟指针指向的数据类型有关 sizeof(数据类型)*n
p++:p向地址增大的方向移动1个数据
int i = 5, j =10;
int *p = &i;
int *q = &j;
p-q:两个指针之间相隔元素的个数(p、q必须是同类型的指针)
int arr[5] = {1,2,3,4,5};
int *p = arr;
int *q = &arr[4];
printf("%d",q-p); 4
注意:
同类型的指针不可以进行相加、相乘、相除
2〉关系运算
> < >= <= == !=
两个指针必须是同类型的,而且必须指向同一数据区域才可以进行关系运算
指针s q指向同一数据区域
指针可以和0进行比较,判断指针是否为空
7.指针与一维数组
int arr[5] = {1,2,3,4,5};
int *p = arr;//指针变量P指向了数组的首元素
p = &arr[0] =arr
p+1 = &arr[1] =arr+1
p+2 = &arr[2] = arr+2 ....
!!!*p = *&arr[0] = arr[0] = *arr =p[0]
*(p+1)= *&arr[1] = arr[1] =*(arr+1) =p[1]
*(p+2)= *&arr[2] = arr[2] =*(arr+2) =p[2]
*(p+3)= *&arr[3] = arr[3] =*(arr+3) =p[3]
*(p+4)= *&arr[4] = arr[4] =*(arr+4) =p[4]
注意:arr++ ----->error
arr是个地址常量,p是个变量,所以数组名在运算中可以作为指针参与运算,但不可以被赋值
*(s+1)!!!!!!!!!!!违法操作
*s++----------*(s++)---先将s++表达式的值得出再取值
六〉作业
D对
A对-----常量区不能被修改
D对-----------将p(一个未知地址)的值传给了s,但后来字符数组的首地址又给了s,所以最后没有对p所指向的地址操作,FUN函数没有返回值,子函数执行完就被销毁,因此为P所指向的地址空间随机
八:C基础(七)
一〉计算机内存分布:
二〉二级指针
int i = 5;
int *p = &i; //p的数据类型:(int *) *p的数据类型:int
int **pI = &p; //pi的数据类型:(int **) *pi的数据类型:(int *) **pi的数据类型:int
*p = i = 5;
*pi = p = &i; //*pi就是p的一个别名,操作*pi就是在操作p
**pi = *p = i = 5; //**pi是i的别名,操作**pi就是在操作i
1.指针与二维数组
int arr[2][3]= {1,2,3,4,5,6};
//定义一个指针指向数组中的第一个int元素
int *p = &arr[0][0] = arr[0];
p = &arr[0][0] = arr[0]
p+1 = &arr[0][1]
p+2 = &arr[0][2]
p+3 = &arr[1][0]
p+4 = &arr[1][1]
p+5 = &arr[1][2]
*p = *&arr[0][0] = arr[0][0] = *arr[0]
*(p+1) = *&arr[0][1] = arr[0][1] = *(arr[0]+1)
*(p+2) = *&arr[0][2] = arr[0][2] = *(arr[0]+2)
*(p+3) = *&arr[1][0] = arr[1][0] = *(arr[0]+3)
*(p+4) = *&arr[1][1] = arr[1][1] = *(arr[0]+4)
*(p+5) = *&arr[1][2] = arr[1][2] = *(arr[0]+5)
for(i=0;i<6;i++)
{
printf("%d",*(p+i));
}
int arr[2][3]= {1,2,3,4,5,6};
//定义一个指针指向二维数组的首元素,此时首元素名称:a[0]---a[2],数据类型:int [3]
数据类型 * 变量名
数组指针--(指向二维数组其数据类型为int [3]):int (*p)[3]; //[]的优先级比*高,所以*p必须要括起来
sizeof(p) = 4
p = &arr[0] = arr;
p+1 = &arr[1] = arr+1
*p = *&arr[0] = arr[0] = &arr[0][0] = *arr //*p是一个地址
*(p+1) = *&arr[1] = arr[1] = &arr[1][0] = *(arr+1)
**p = *(&arr[0][0]) = arr[0][0] = **arr = p[0][0]
**(p+1) = *&arr[1][0] = arr[1][0] = **(arr+1) =p[1][0]
arr[0][1] = *&arr[0][1] = *(&arr[0][0]+1) = *(*p+1)
arr[0][2] = *&arr[0][2] = *(&arr[0][0]+2) = *(*p+2)
arr[1][1] = *&arr[1][1] = *(&arr[1][0]+1) = *(*(p+1)+1)
arr[1][2] = *&arr[1][2] = *(&arr[1][0]+2) = *(*(p+1)+2)
arr可以看成是一个二级指针
int arr[5] = {1,2,3,4,5};
int * p = &arr[0] = arr; //定义一个指针指向数组中的首元素
int (*p1)[5] = &arr; //定义一个指针指向整个数组
2.指针数组:
int *p[2]; //定义了一个长度为2的数组,数组的元素都是一个指向int的指针
sizeof(p) = 8
int m = 5;
int n = 10;
p[0] = &m;
p[1] = &n;
p = &p[0]
*p = *&p[0] = p[0] = &m
**p = *p[0] = *&m = 5
*(p+1) = p[1] = &n
**(p+1) = *p[1] = *&n = 10
3.字符指针
char str[20] = "helloworld";
char *pc = str;
char *pc1 = "helloworld"; //字符串常量本身就是字符串的首地址
(1)scanf("%s",str); ok
scanf("%s",pc1); error 不可以对常量区的内容进行修改
(2)printf("%s",str); ok
printf("%s",pc1); ok
(3)str[1] = *(pc+1)
*(pc+1) = 's'; ok
*(pc1+1) ='s'; error 不可以对常量区的内容进行修改
(4)char *pc1 = "helloworld"; ok
char str[20];
str = "helloworld"; error str是一个地址常量
注:常量只可被读,不能修改
三〉函数
(1)函数的作用:使我们的程序变得更加模块化,同时可复用性更强
(2)函数的分类
库函数:
1)先引入头文件
2)调用函数
如果函数有返回值,变量 = 函数名(实际参数1,实际参数2...)
#include <stdio.h>
printf("字符串",实际参数2,实际参数3...)
自定义函数:
1)函数声明 //告诉计算机有这个函数
返回值类型 函数名(形式参数1,形式参数2...);
//形式参数必须要写数据类型,变量名可省略,句末一定要有分号,返回值如果没有写void
2)函数定义
返回值类型 函数名(形式参数1,形式参数2...)
{
函数体;
return 变量名; //如果没有返回值,该句话可省略
}
//函数定义的时候形式参数的变量名一定不能省
3)函数调用
变量 = 函数名(实际参数1,实际参数2...)
调用子函数结束,给子函数分配的这片空间就被销毁
在调用子函数之前,如果该子函数已经定义,那么可以不写函数声明
如果该子函数的定义在调用子函数之后,那么必须写函数声明
全局变量:定义在函数体外部的变量 作用域:自定义开始到文件结束
局部变量:定义在函数体内部的变量 作用域:自定义开始到最近的}结束
四〉gdb调试工具
(1)编译的时候添加参数 -g
gcc -g cal.c -o cal
(2)进入gdb
gdb cal
(3)设置断点
b main //在main函数处设置断点
b 30 //在第30行处设置断点
(4)r(run) 运行
(5)n(next) ---->不进入子函数
(6)s(step) ---->进入子函数
(7)q(quit) ----->退出
(8)回车代表执行上一个命令
五〉static
修饰局部变量:如果该变量没有被初始化,那么就被初始化为0;如果已经被初始化,那么就只能被初始化一次
修饰全局变量:该变量只能在本.c文件使用
修饰函数:该函数只能在本.c文件使用
static修饰全局变量
static修饰函数
隐藏,只允许在本文件中调用,不允许在其他文件文件中调用
static修饰局部变量(增长变量的生命周期);
首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。
六〉作业:
用子函数实现两个数的交换
void change(int *a,int *b)
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
int main()
{
int m,n;
m=1;
n=2;
printf("m=%d n=%d\n",m,n);
change(&m,&n);
printf("m=%d n=%d\n",m,n);
return 0;
}
九:C基础(8)
一〉结构体
1. 定义:
构造一个新的数据类型
struct person{
char name[20];
int height;
};
该数据类型叫 struct person
typedef struct person per;
typedef struct person{
char name[20]; //成员变量之间要用分号隔开,成员变量的数据类型可以相同也可以不同
int height;
}per;
初始化:per p1={"lijianfei",175};
访问结构体成员变量:结构体变量名.成员变量名
输出:printf("%s %d\n",p1.name,p1.height);
输入:scanf("%s%d",p1.name,&p1.height);
//定义一个指针指向p1
per * pper;
pper = &p1;
*pper <====> p1
(*pper).name (*pper).height
//通过结构体指针访问成员变量
指针变量名->成员变量名
pper->name
pper->height
//定义一个结构体变量p2
per p2;
p2 = p1; //将p1的值赋值给p2
p2.name p2.height
2、字节对齐(32OS gcc编译器)
系统一次性分配的字节数是成员变量里面最大的字节对齐数
3、共同体
union union{
char ch;
int i;
};
注意:共同体所占内存空间取决于成员变量中最大的内存空间 sizeof(union un) = 4
共同体中所有成员变量的首地址都是一致的,所以在某一时刻只能取一个成员变量使用
//定义一个共同体变量
union un u1;
4、大小端
大端序:低字节存高地址处,高字节存低地址处
小端序:低字节存低地址处,高字节存高地址处
判断计算机是大端序还是小端序:(通过共同体)
u1.i = 0x12345678;
if(u1.ch == 0x78)
printf("小端序\n");
else
printf("大端序\n");
5、Const
const 数据类型 变量名; //该变量只读
const int a = 10;
a = 20; //error a只读
const char *p = "helloworld";
char str[20] = "helloworld";
const char *p = str; //<====>char const *p = str;
*p = 'e'; --->error str这片空间只读
char * const p = "hello";
p就只能指向“hello”这个字符串,不能再指向其他字符串
const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的安全性和可靠性。另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。另外CONST在其他编程语言中也有出现,如C++、PHP5、C#.net、HC08C。
3、指针函数:返回值是指针的函数就是指针函数
LINUX C
一:SHELL基础3
一〉嵌入式系统3
二〉Linux软件管理机制3
1. dpkg-----3
2.apt_get-3
3.apt-cache-3
三〉APT软件包管理器3
四〉LINUX系统结构4
五〉SHELL命令5
六〉通配符6
七〉输入输出重定向6
八〉命令置换7
九〉进程管理7
十〉linux文件系统8
1.文件系统类型8
2.SCSI(机械硬盘)与IDE8
3.根目录文件9
4.文件类型10
5.创建链接文件:10
6.文件压缩与解压10
二:shell脚本编程基础11
一〉编写流程11
二〉:变量11
1.自定义变量11
2.位置参数与预定义变量11
3.环境变量12
三〉shell程序和语句12
1.语句12
1〉说明性语句13
2〉功能性语句13
3〉结构性语句15
四〉shell函数21
1.定义21
2.传参:21
三:c高级23
一〉引入23
二〉数组24
1:一维数组24
2:二维数组--按行存放24
三〉指针24
1:值访问25
2:运算25
3:一维数组与指针25
4.指针与二维数组26
5.指针数组27
6字符指针数组27
7:多级指针28
8:const/void指针28
四〉函数29
1.函数定义:29
2.函数声明:29
3.函数传参30
1〉复制传参30
2〉地址传递30
3〉全局变量31
4.指针函数31
5.函数指针32
六〉递归函数34
七〉GCC编译器35
1.编译运行步骤35
2.GNU工具35
3.定义-交叉平台编译器35
4.主要组件35
八〉GDB(用途小36
九〉结构体**36
1.结构体数组37
1〉定义struct stu a[3];37
2〉初始化38
3〉提取元素38
2.结构体指针38
3.结构体指针数组38
十>内存分配***39
1.存储模型39
1>变量39
2.动态分配39
十一〉makefile基本结构39
1. 工作原理40
2.基本格式40
一:SHELL基础
一〉嵌入式系统
X86 arm---体系架构
MIT---麻省理工
Ubuntu----”人道待人”理念
艾伦.图灵---计算机之父
Richard staliman-----自由软件之父(GNU运动(软件开源,免费)----gcc.gdb.gedit)---->GNU/Linux(在GNU运动下开发的LINUX系统)
嵌入式应用:无人驾驶----利用声呐不断测试与障碍物的距离来控制车速
二〉Linux软件管理机制
三个配置文件:
软件源配置文件(软件仓库):/etc/apt/sources.list
本地软件包索引文件(可下载的目录):/var/lib/apt/lists
本地文件下载缓存目录:/var/cache/apt/archives
- dpkg------
完成本地软件包安装管理(依赖关系明确)
注:在/var/cache/apt/archives(本地缓存目录---安装包存放的地方)下输入命令
命令:sudo dpkg -i <package(完整的安装包文件名--就在上面的那个目录下可以查看)>:安装软件
Sudo dpkg -P <package>:移除已经安装的软件包及配置文件
2.apt_get---管理下载文件
步骤:1:查找软件最新版本 2:配置文件依赖关系 3:下载 4:安装
Sudo apt-get install (-d) packg------下载并安装(不安装)
Sudo apt-get remove/clean/update/upgread/check(卸载/删除已下载的包文件/下载更新软件包信息列表(包括更新软件源里的软件信息)/升级到最新版本/查看系统中依赖关系的完整性) [-d/--purge/--reinstall/-v/-f] (仅下载不安装/与remove连用完全卸载(包括软件包与文件)/重新安装/获取版本号/修复依赖关系)packg
3.apt-cache---查询软件相关信息
Apt-cache show/search/policy/depend(获取二进制软件包的详细信息/检索软件包/获取安装状态/获取依赖关系)
三〉APT软件包管理器
---1:检查修复软件包依赖关系 2:利用网络主动获取软件包
deb软件包(ubuntu系统):二进制软件包(deb)--可直接安装 源码包(deb-src)--需解压再安装
rehat系统:rpm软件包
四〉LINUX系统结构
- Shell是一个命令编译器,将用户命令编译成二进制程序,交给操作系统执行。【 F】??
- 在默认情况下,所定义的Shell变量的作用域是局部有效。【 F】
- 使用DHCP服务配置动态IP的过程,就犹如一个租借过程。【T 】
linux内核含有硬件驱动控制硬件,硬件做出相应的反应来控制shell,shell再将信息反馈给用户
SHELL---命令行解释器(更快更直接)
当前使用版本--bash(bourn again shell)<------sh(bourn shell)的增强版
五〉SHELL命令
Sudo shoutdown -h n/now--关机
Ctrl+c---取消关机
Sudo shoutdown -r n/now---重启==reboot(直接执行boot-loder(系统引导程序))
命令---指令 选项 参数
Ls -l DS/----显示DS目录下的内容
多命令在一行同时执行-----命令1;命令2..(ls;pwd)
一个命令在多行------命令.........
\命令.....
Tab---命令补齐
(两次tab)----显示当前目录下具有相同前缀的名称
Less/more -----分页显示
查询历史命令:history n(默认500行)
设置历史命令容纳量:HISTSIZE =m
Echo $HISTSIZE----查看
基本系统维护命令
Passwd---修改密码(root 可修改其他用户的(su))
Cd /home/----用户主目录
Export----查看环境变量----可以修改其中的环境变量(su -m)
Echo----显示指令(当有多个空格时只打印一个(认为其为一个指令))
Echo “ ”---显示字符串
Echo $PATH--查看当前编译路径
???Mips--:交叉编译
Date--查看当前时间
While(1)
{
System(“date”);
Sleep(1);
}//每秒打印一次时间
??????Date -s “%y-%m-%d”
**********df--查看磁盘空间使用率(tmpfs--虚拟内存空间:1G的虚拟内存可虚拟出4G的内存空间)
Df -a-----显示所有的文件系统使用情况(包括proc,sysfs虚拟内存)
Df -ah--以M为单位显示
Du----显示每个文件/目录所占磁盘块数(每个磁盘占512个字节)
/etc/passwd 文件----用户清单(p86)
/etc/group 文件-----组与成员列表(p89)
Adduser <用户名>----创建用户
************/etc/skel目录----被/etc/sbin/adduser使用,将新用户想要的配置文件拷贝到/etc/skel中
Usermod---修改用户属性(推出登陆root用户)
sudo usermod -l newname oldname(修改用户名)
sudo usermod -d /home/user1(全新目录) -m(将家目录搬到新目录下,与-d一起使用) -l newname oldname --------------------(修改用户名并修改家/主目录))
Sudo deluser name----仅仅删除用户名,相关文件还存在
Sudo deluser --remove-home user1-----删除用户并删除用户目录
/etc/adduser.conf---- 用户配置文件
Sudo delgroup groupname---删除组
Exit----退出用户
*********************************
六〉通配符
1〉‘*’---匹配任意长度的字符串(file_*.txt)
’?’----匹配一个长度的字符
‘[]’---匹配其中指定的一个字符(file_[ot].txt==file_o.txt,file_t.txt)
‘[ - ]’-------指定的一个字符范围([a-z])
‘[^ ]’-----除了其指定的字符
管道:‘|’-----第一个命令的输出作为第二个命令的输入
Eg:ls /usr/bin | wc -w-----统计指定目录下的文件数目
七〉输入输出重定向
1〉‘〉file’---覆盖输入重定向
2〉‘〉〉file’----追加输入重定向
3〉‘〈file’---覆盖输出重定向
4〉‘<<file’---追加输出重定向
’2>file’-----错误覆盖输出重定向
‘2>>file’----错误追加重定向
Eg:ls 2.c 2> e.c
Char * fgets(char *s,int size,FILE *stream);
Fgets(str,10,stdin)----从缓冲区获取指定长度的字符(stdin(标准输入) stdout(标准输出))
流;标准输入流-------》文件描述符 0
标准输出流 1
标准错误流 2
八〉命令置换
命令1 `命令2`------将命令2(esc键下的但引号)的结果作为命令1 的参数
Eg:ls `pwd`
九〉进程管理
程序==数据结构+算法 静态
进程:程序的一次执行
命令:
Ps -au ---〉仅显示当前用户的进程详细信息
%cpu---cpu占用率 %MEM---内存占用率 VSZ--虚拟文件使用字节数 RSS---占用磁盘字节数 TTY---正在使用的配置文件 STAT--状态 START---运行时间
Ps -aux ---->显示所有用户进程信息
Top ----实时监控进程: NI----进程优先级 PR---进程控制块
???????Nice -----调整进程优先级
KILL PID-----终止进程==ctrl+c(向内核发送KILL9)(强制终止进程)
进程状态
Z---将死态(没运行,但占一部分空间) L不重要
‘+’----进程挂起
十〉linux文件系统
1.文件系统类型
df查看磁盘空间
磁盘文件系统:
网络文件系统:NFS(文件系统)---系统移植应用
专有/虚拟文件系统
2.SCSI(机械硬盘)与IDE
固态读写快,作为系统盘15秒开机了解一下。240g再储存点常用软件和网游绰绰有余了。
机械读写慢,但可以作为储存文档,电影等数据之类的硬盘,相对于固态也更安全,更稳定。如果固态的容量不够可以考虑再加一个机械。如果240g就够用的话也没必要再加机械。
内存----内存条(执行程序时的变量等)--断电重启后数据不在
外存----a.out存在磁盘空间---断电重启后数据还在
IDE--固定硬盘
Sata---机械硬盘
交换分区----交换分区(了解)(将内存内容写到磁盘,或从内存读出)
3.根目录文件
/(linux文件系统根目录) /bin(存放系统中最常用的可执行文件(二进制文件))
/boot(存放Linux内核和系统启动文件) /dev(设备文件)
/etc(配置文件,用户信息文件等) /home(用户主目录)
/lib(存放共享的库文件) /mnt(存放被挂载文件的挂载点----可用于文件共享)
/proc(存放所有标志为文件的进程) /root(超级用户主目录) /var(存放长度可变的文件)
Linux与windows区别
EXT4---LINNX现在最新文件格式 FAT64--windows常用文件格式
最大区别:(换行符区别)LINUX---\n windows---\r\-n
4.文件类型
命令:
File <name>---查看文件类型
Cp 目标 被复制 -r ----------------复制目录
Mv day2/ ~ ---移动到家目录
Mkdir -p mm/kk/ll
LINUX不会显示二进制内容 cat a.out---结果是乱码
Head -n name tail -n name-----显示头尾指定行数
5.创建链接文件:
硬链接:利用linux分配的物理编号--inode建立链接-----不能跨越文件系统---不可恢复
软链接:利用文件的路径名建立链接(相对路径)--可恢复(重新创建一个同名的link-name链接又会重新启动)
ln [-s(软链接)] target link-name(改变target的内容Link-name的内容会相应的改变)
6.文件压缩与解压
归档文件(.tar):将一组文件或目录保存在一个文件中---使占用磁盘空间增大
压缩文件(.gz):将一组文件或目录保存在一个文件中,并以某种存储格式存储在磁盘空间上,内存总和比所有文件之和小
1〉Gzip工具:有链接文件不能被压缩打包(windows无链接文件)
Gzip -d/-l/-num(1-9)(解压/查看压缩文件内的信息/指定压缩比率(默认6),数字越大压缩力度越大) name
Gunzip [-f] (提示已经有的同名文件)name-----解压
2〉Tar命令(归档文件):[-c] tarname filename
Tar -cf 123.tar 1.c 2.c 3.c ---->tar -xvf 123.tar 创建一个新的归档文件
Tar -xfv 123.tar -----解压并显示指定归档文件
Gzip -d 123.tar --->解压==gunzip
二:shell脚本编程基础
运维师与外挂
shell区分大小写
一〉编写流程:#!/bin/bash(当前使用的脚本类型,执行该文件的程序)--开头一行(!虽然注释掉了但系统可以阅读)-----------〉编写程序并保存退出----〉给文件设置执行权限(chmod 权限 文件名)-----〉./x.sh(运行程序)
二〉:变量
1.自定义变量(默认为全局变量)
变量名=值
取用变量值:$变量名6g
Num=20
Unset num
2.位置参数与预定义变量
c语言中:int main(int argc ,char *argv[])命令行参数
$?-返回调用函数的返回值
3.环境变量
$HOME--引用
PATH(默认路径,执行shell脚本时可以快速找到):---shell可执行的路径(将x.sh放在其路径下,不用指定其路径(x.sh直接运行))
执行程序必须知道其存放路径:./x.sh
/bin-----存放基本的指令(二进制可执行程序)
DATE=`date`----命令置换 LIST=`list`
Unset---取消环境变量,在命令行输入:unset z
Set---设置环境变量
三〉shell程序和语句
1.语句
比较---条件测试语句
1〉说明性语句
2〉功能性语句
Read----阻塞功能,被read赋值的变量不允许再次被赋值,read 可被回车终止
Read var1 var2 var3
注:运算符左右两侧必须加空格
‘*’----通配符,利用‘\’去除二义性
$num=9---$命令行提示符
I++------->$i=`expr $i + 1`(x) 对:i=`expr $i + 1`
test==[ x ]
$?(上一条命令的结果)------0为真,非0为假
Z--zero n--no
eq==等 ne==not eq gt==big than ge==big eq lt==last than le==last eq
text测试时“=”两边必须有空格
-d(目录文件) -f(普通文件)重要
整数测试时-ge等表达式, 前后都是需要数字类型的变量或者常量, 一般都是${xxx} 不用加双引号
3〉结构性语句
分支语句
注:条件(test) ’[]‘里面最左边与最右边必须有空格
-a(逻辑与) -o(逻辑或) !(逻辑非)
If [ 条件 ]
Then
Elif [ 条件 ]
Then
Else
fi
Let 指令--取十位 ‘|’将多个项合并
循环语句
实现1-100的和 将当前目录下的所有文件拷贝到上一级目录
‘*’可打印出当前路径下的所有文件名
仅仅打印当前路径
创建文件 :$1$i--文件名,从键盘输入file 3
删除文件:命令行输入file 1 3
if [ $# -eq 3 ]
then
count=$3
else
echo input error
exit
fi
i=$2//1
while [ $i -le $count ]
do
rm $1$i # file1 file2 file3
let i++
done
循环控制语句
第一次$output为空
作业:用shell打印9*9乘法表
Echo (默认换行) 参数选项: -n 输出文字不换行
-e 将转义符跟后边的特殊字符解释成特殊意义
-E 不解释转义字符
1〉#!/bin/bash
For i in {1..9}
Do
Foe j in {1..9}//error----{1..$i}
Do
If [ $j -le $i ]
Then
Let sum=$i*$j
Echo -ne “$j*$i=$sum\t”//\t----水平制表符
Fi
Done
Echo
Done
2〉
for ((i=1;i<=9;i++))
{
for ((j=1;j<=$i;j++))
{
let sum=$i*$j
echo -ne "$j*$i=$sum\t"
}
echo " "
}
3〉
\t----水平制表符
四〉shell函数
1.定义
2.传参:
‘..’传给$1 “-aux”传给$2
实现两个数相加($?获取上一程序的状态)
abc为全局变量123 456
设置局部变量:local 变量名
打印出123 123
三:c高级
一个寄存器只有十多个字节。定义寄存器变量时,也存放在栈区
一〉引入
判断寄存器存储变量与AUTO变量执行速度
Time(&sttar)---以秒统计时间
For(;j<=N;j++);
Time(&stop);
Printf(“%d\n”,stop-start);
Time_t t;time(&t);//将从1970.1.1到当前时间的秒数赋给变量t,
printf(“today’s time and date is %s”,ctime(&t));------打印出当前日期与时间(ctime(&t)将秒数转换为日期与时间)
二〉数组
1:一维数组
Int n=10;int arr[n];(对)
Int n=10;int arr[n]={1,2,3,4};(错)---n为可变值
初始化时,才被分配空间
gcc编译不能查看数组越界
str后面存放str1打印结果---hellohaa
2:二维数组--按行存放
Arr=&arr[0]
Arr[0]=&arr[0][0]
因为arr[0]与arr[0][0]的地址重合因此打印出的地址相同,但是*(arr)=&arr[0][0]为一个地址,而*(&arr[0][0])=arr[0][0]--为一个值
三〉指针
地址--内存单元的编号
此时野指针并没有被使用因此不会报错
空指针 ---物理--0地址
---逻辑-不会指向任何地方(与野指针相对)
Int *p=NULL<==>int *p=0;(0为NULL的编号)vi /user/lib/gcc/.....(宏定义地址)
1:值访问
Int n=20;int *p=&n;
Int *p = (int *)100;(强制转换)对---
1〉直接访问:n=20 2>间接访问:*p=20-----寄存器只能间接访问
‘*’-----解引用符
2:运算----实质是地址的偏移
1>两个指针之间不能进行‘+’ 2〉倒叙字符串
3〉数据类型不匹配,无法获取想要的数据,将返回0
3:一维数组与指针
a为地址常量,只读,a++错
1〉求最小值
4.指针与二维数组
二维数组元素名,为行地址
数组指针--〉行指针只能指向二维数组---int (*p)[3]=a//[二维数组的每个元素里有多少个数据]
p[i] <-->*(p+i)-----*/ []:降维作用
P[i][j]----1:将p[i]看作一个整体将其解引用得(*(p+i))[j]-----将[j]先解引用*(p[i]+j)-----将两个都解引用*(*(p+i)+j)
5.指针数组
Int *a3[2]-----[二维数组元素个数]
a2,a4所存内容一样,为同一片内存空间,只是行列数划分不同,但对其操作不会越界
A2[2][3]; 1 2 3/4 5 6/
A4[3][2]:1 2/3 4/5 6/
6字符指针数组---存放的为字符指针常量的首地址,不能被修改
Char *str[5]:指针访问常量区,字符串 常量 char str1[]:字符串变量
printf(“%c”,**y);---h y++--->段错误
7:多级指针
二级指针--指针的地址
&(char *)
打印出world 打印出e
P+1------地址偏移4个字节,因为其中存的字符串地址占四个字节
二级指针与二维Int数组
Int **p=b----p指向a[0]
*p+1---第一行再移一个
8:const/void指针
1〉Const---修饰一个变量为只读
Eg:strcat(char *dest,const char *src)
Strcat(dest,”http”);
修饰指针:
1〉
Int const *p=&n;//*p不能修改
指针数据类型与所指对象的数据类型要相同
2〉void 指针
Void *p=&a;
引用:*(int *)p
---可指向任意数据类型--但因无确定的数据类型,无法知道取多少空间里的数据,因此需要强制转换
四〉函数
1.函数定义:完成某些特定功能的代码模块。形参名不可省
2.函数声明:若函数定义写在main函数之后,就必须写. 形参名可省
Eg:int add(int ,int ); int add(int a,int b);
注:个代码程序,有且仅有一个main函数
3.函数传参
1〉复制传参
实参并没发生交换
2〉地址传递
Swap(&x,&y)
仅仅将p q里面的内容传给了子函数,而p q地址不变----------相当于复制传递
实现了两个实参值的交换
传递函数:一维整型数组,字符数组传参,二维数组
地址传参:int (*a)[3] int a[][3]--复制传参 但两者都是地址
3〉全局变量---定义在所有函数之外
Int flag;
Func(flag)
static变量与全局变量不做初始化,初始化默认为0----放在静态变量数据区
Eg:
N--二维数组行 m----二维数组列
4.指针函数----返回值为地址
Eg:
p--变量的值,str3----地址
函数可以返回一个值:p可以返回,并由p存储的地址里面的内容依然存在,而str3能返回,但其内容已经被销毁,因此不能返回一个局部变量的地址
当static修饰时,可以返回str里面的内容
Static:(变量存放在静态存储区)
一:修饰局部变量----增长了变量的生命周期
二:修饰函数:限制函数的作用域,只能在当前文件中被调用
三:修饰全局变量:限制变量作用域,只能在本文件中使用
static可由程序员手动放入堆区,没有运行的代码放入代码段中
5.函数指针==函数名
定义:存放函数地址的指针
函数返回值类型 (*指针名)(函数参数类型)
指针指向函数:函数名就为函数的起始地址
q==add-->add[10,20]==q[20][20];
Char * (*p)(char *,char*)
小应用:float decall(float (*fp)(int),int n)//float (*fp)()函数指针
{
float s;
s=(*fp)(n);//调用函数指针
return s;
}
五〉函数指针数组
调用:
六〉递归函数(做题)
1〉自己调用自己 2〉寻找递归终止条件
先递推再回归
例子:5!
七〉GCC编译器(GNU CC)
1.编译运行步骤
1: .c ----->.i 2: .i--〉.s 3: .s-->.o
.so/----动态库 ./a静态库 ----------cd /lib
2.GNU工具
3.定义-交叉平台编译器
4.主要组件
分析器:将源语言程序代码转换为汇编语言
汇编器:将汇编语言代码转换为CPU可执行字节代码(二进制文件)
链接器:将汇编器生成的单独目标文件组合成可执行的应用程序
标准C库:标准的C函数都由C库提供
生成汇编文件----〉检查语法错误
八〉GDB(用途小)---数组越界
----printf()代替,查看错误 printf行缓存函数---当输出内容占满一行才输出,因此需利用’\n’来结束一行的缓存
九〉结构体***
---数据结构的链表使用
结构体对齐标准:最长字节对齐方式(编译器不同对齐不同),GCC是4字节对齐方式
1.结构体数组
1〉定义struct stu a[3];
2〉初始化
3〉提取元素
4:结构体调用结构体
-----调用
2.结构体指针
1:定义 2:调用
3.结构体指针数组
十>内存分配***
1.存储模型
1>变量
全局变量与局部变量---若两个变量名相同,在局部就对局部变量进行操作
具有外部链接的静态 :外部链接,所有函数之外
具有内部链接的静态 :内部链接(static),所有函数之外
空链接的静态 :局部变量+static
2.动态分配-----heap(堆区)
----应为malloc返回为void *因此需强制转换为与p的数据类型相同的空间
Free()---仅仅需要释放空间的首地址
十一〉makefile基本结构
----------工程管理器
1.工作原理
make工程管理器根据( 文件时间戳 )来自动发现更新过的文件从而减少编译的工作量。
2.基本格式
避免头文件重复定义
sunq为可执行程序
$@ $^:所有的依赖文件