VMware -- 虚拟机 Ubuntu -- 以Linux为内核的开源免费的操作系统 Linux 一切皆文件,支持多用户登录
终端操作
root@ ubuntu : ~ $ 用户名 分隔符 主机名 分隔符 家目录 普通用户提示符 sudo + 命令 临时拥有超级用户的权限 / 根目录 /home/hqyj 家目录 文件夹 -- 目录
基本命令
命令 [参数选项] [文件] ... man 命令 查看帮助手册 pwd 查看当前路径 ls 查看当前路径下文件 ls -l 列出文件的详细信息 Downloads 文件类型 主用户权限 同组用户 其他用户 链接数 用户名 组名 大小 日期 ls -a 查看所有文件,包含隐藏文件 cd 切换路径 cd 路径名 绝对路径: 从根目录出发,一级一级递进,不容易出错 相对路径: 相对于当前位置,文件的所在路径 ../ 上一级目录 ./ 当前目录,大部分时候省略了 cd 直接回车,一键回家 cd - 回到上一次操作路径 mkdir 创建目录文件 touch 创建普通文件,更新时间戳 rmdir 删除空目录文件 rm -r 删除目录文件(空和非空都能删除) rm 删除普通文件,彻底删除,找不回来
常用快捷键
Linux的文件类型: linux工具 vi/vim操作 clear 清屏 exit 关闭终端 cp 源文件 目标文件 复制普通文件 cp -r 源目录文件 目标目录文件 复制目录文件 mv 源文件 目标文件 若目标文件存在,则是移动源文件到目标文件内 若目标文件不存在,则是将源文件重命名为目标文件名 cat 文件名 直接将文件内容输出到终端界面 ifconfig 查看网络ip ping ip地址 查看两边网络是否能通信 ctrl + l 清屏 ctrl + shift + ‘+’ 放大字体 ctrl + '-' 缩小字体 ctrl + alt + t 新建终端窗口,默认家目录路径 ctrl + shift + t 新建窗口标签,在已有终端的情况下操作 ctrl + shift + n 新建终端窗口,在已有终端的情况下操作,新建的终端和上一个终端路径相同 alt + 数字 切换标签 alt + tab 切换界面 tab 自动补全命令或文件名 键盘的上下箭头,翻看历史命令 ctrl + c 强制结束程序 ctrl + z 将程序移动到后台运行,通过fg命令又回到前台运行
linu文件类型
7种, 不以后缀区分 普通文件-图片、音频、视频、文档。。。。 d 目录文件-文件夹 c 字符设备文件(驱动) l 链接文件 (linux基础学习) b 块设备文件(驱动) s 套接字文件(网络编程) p 管道文件(进程时学习)
linux工具
编辑工具: vim/vi gedit 编译工具: gcc g++ linux-arm-gcc
vim/vi操作
三种模式:命令行模式、插入模式、底行模式 命令行模式: yy nyy dd ndd p u 撤销 ctrl + r 反向撤销 gg 跳到文档开头 G 跳到文档末尾 gg=G 代码自动对齐 /string 查找,n 查下一个 N 查上一个 从命令行模式,进入插入模式: a i o A I O 退出插入模式,回到命令行模式: esc 从命令行模式,进入底行模式: : :q 退出 :wq 保存并退出 :w 保存 :x 保存并退出 :q! 强制退出 :n 跳转到第n行 :set mouse=a 使光标能随鼠标点击移动 :set mouse=v 能在vi内使用右键复制的功能 :/string 查找,n 查下一个 N 查上一个
GCC编译器
命令形式:gcc file.c
vi hello.c
gcc hello.c 生成a.out
运行
默认会生成一个叫做a.out的可以执行的二进制文件,./a.out表示执行这个文件
gcc file.c -o [name]
-o参数表示重新命名生成的二进制文件
gcc编译步骤
预处理->编译器->汇编器->链接器
预处理:展开头文件,进行宏替换
gcc -E file.c -o file.i
编译:产生语法错误
gcc -S file.i -o file.s
汇编:转换汇编代码生成二进制文件(这个二进制文件并不能直接执行)
gcc -C file.s -o file.o
链接:生成的二进制文件和一些运行条件(库)连接诶在一起生成可执行的二进制文件
gcc file.o -o name
C基础
机器语言-数据进制
二进制:只有0和1表示的数据,逢2进1
十进制和二进制的互相转换:除2取余倒排,凑数法,计算器
八进制:范围在0-7,逢8进1(以0开头,用于和十进制做区分)
07777 066
八进制和二进制的互相转换:一位换三位
十六进制:范围在0-9,A-F,一般来说以0x开头的是十六进制
0x123 0x1a4
十六进制和如今只的互相转换:一位换四位
数据的形式
数据的原码,反码,补码
正数:14->1110(存放原码) 反码1110->正数的补码就是原码
负数:-1(1个字节的数据)00000001->1111110(反码)补码等于反码等于补码+1->11111111
总结:正数在内存中存放的就是它本身,负数是以补码的形式存放在内存中(原码取反再加1)
常量
概念:表示在程序中不能够被更改的内容
100,‘a’ , "hello"
宏:
#define MAX 100 printf("%d\n",MAX);
变量
概念:内存中的一个空间,可以用来存放诸多形式的数据,而且数据可以被改变
变量的声明:
<存储类型><数据类型><变量名>; int a;存储类型:auto register static extern
auto:表示自动存储,默认情况下就是使用的
auto register:寄存器类型,速度快,数目少
static:静态存储修饰局部变量,变量的生命周期延长
内存中的一片空间,可以用来存放不同的数据
声明形式:
<存储类型><数据类型><变量>; int a;char b;存储类型:auto register static extern
auto:自动给存储,缺省情况下默认使用auto
register:寄存器类型,速度快,数目少。需要申请,申请不到自动转为auto
static:静态存储,只会初始化第一次
修饰局部变量的时候,生命周期延长,作用域不变
修饰全局变量的时候,生命周期不变,作用域被限制(只能在本文件中使用)
修饰函数的时候,生命周期不变,作用域被限制
extern:引用外部定义,通常跨文件的函数可以为extern
数据类型:表示这片空间用于存放什么类型的数据(空间大小和特点)(内置)
char:字符类型 1个字节 -128~127 char a='A'; char b='Z'; char c=48; unsign char 0~255 short:短整型 2个字节 0~65535 • 通常用于网络中的端口号 int:整形 4个字节 long:长整型 在32位系统下4个字节,64位系统下8个字节 • long long float:单精度浮点数,保留到小数点6~7位 double:双精度浮点数,保留到小数点后15~16位 • 8个字节大小变量名:遵从标识符命名规则
1.不能与关键字重名 int int = 10;//错误 2.不能以数字开头 int 2a = 100;//错误 3.只能以字母或下划线开头 int _a,a3;
全局与局部
全局变量:声明在所有函数体外,生命周期和整个程序一致
全局变量不初始化,编译器自动赋值为0
局部变量:声明在函数体外,生命周期和函数调用的周期一致
局部变量不初始化,编译器不会赋值(随机值)
高版本的编译器和系统下,编译器会给未初始化的变量赋值为0
运算符
算数运算符
+ - * / %赋值运算符
=:赋值,把右边的内容赋给左边 += -= a += 1; // a = a + 1;关系运算符
==:是否等于 >:是否大于 <:是否小于 返回结果要么0要么1(0为假,1为真)逻辑运算符
||:逻辑或,有真为真,假假为假 &&:逻辑与,有假为假,真真为真 !:逻辑取反,如果本身逻辑是假,最后结果为真,本身逻辑为真,最后结果为假*注:短路原则,当判断逻辑与时,前一个条件为假,就不用执行后面的条件
当判断逻辑或时,前一个条件为假,就不用执行后面的条件
自增运算符
++ -- int a = 10; a++; ++a; 前++: 变量的内容先加1,再来使用这个时候的变量内容 后++:先使用变量的内容,再在变量的内容上加1 前--:变量的内容先减1,再来使用这个时候的变量内容 后--:先使用变量的内容,再在变量的内容上减1三目运算符
表达式1?表达式2:表达式3 判断表达式1是否成立,如果成立则使用表达式2的结果,不成立则使用表达式3的结果 a > b ? a : b位运算符
>>:右移运算符,会将数据向右移动1位(移动的是二进制位)相当于除2 <<:左移运算符,会将数据向左移动1位(移动的是二进制位)相当于乘2 |:位或,将二进制的某一个位进行或操作 &:位与,将二进制的某一个位进行与操作 ~:按位取反,将二进制的每一个位0变成1,1变成0 ^:异或,对应两个二进制数据每一个位进行比较,相同的位为0,不同位为1如果有一个数据10001101 要将2、3位清0 10001101 & ~(3 << 2);sizeof运算符
求字节大小
sizeof(int) sizeof(var) 不仅可以直接求数据类型大小,也可以通过变量来求字节大小
类型转换
隐式转换:
在做运算的时候出现了多个类型,有符号会往无符号转,低精度会往高精度转
输入输出
c语言中没有专门用来输入输出的语句,都是通过c库函数来帮助实现响应的功能
输入
格式化输入
int scanf(const char *format,...);“”:双引号引导的叫做格式控制串
%:以百分号开头的叫做格式控制符,可以将相应的变量内容显示出来或者输入进去
*注:在输入的时候,不应该在格式控制串里面添加除了格式控制符以外的内容
*注:在输入的时候,获取内容的变量需要加上取地址符号&
格式控制符:
%d:整型数 %c:字符型 %s:字符串(一个或多个字符组成,以'\0'结尾) %u:无符号数 %f:小数 %x:十六进制 %p:地址”垃圾字符“:使用%c来获取
在输入的时候可能会捕获一些没有意义的数据存放到变量中
*注:scanf在输入的时候会以空格,tab,回车作为一个数据的结束标志
单个字符输入
int getchar(void);
char a = getchar();
返回值:返回输入的内容的ASCLL🐎
字符串输入
char *gets(char *s);
*注:gets函数很危险,不建议使用(gets无法规定输入数据的长度,可能会超过接受数据的存储看空间)
输出
格式化输出
int printf(const char *format,...);
格式控制串:
域宽 %nd 规定输出的数据在n个位里面,如果输出的数据小于n,会在数据前面添加剩余个数的空格 如果输出的数据大于n,那么原样输出 %m.ns 规定域宽的同时,也要截取数据(m位域宽,n为有效字符的个数) 转义字符: \所表示的内容 \n 换行 \t 隔一个制表符 \\ 表示打印斜杠本身转义字符本身是用\来转义八进制数据,可以实现对应ASCLL表上的功能
\xxx表示将这个八进制数据对应的字符给显示出来
单个字符输出
int putchar(int c);
就是把c的内容打印出来,打印字符
字符串输出
int puts(const char *s);
就是把s所指向空间的字符串打印出来,自动换行
结构化编程
判断、选择、循环
判断
if(表达式){ 语句块1; }else{ 语句块2; } 判断表达式是否为真,如果为真则执行语句块1;如果为假则执行语句块2 语句块1和语句块2只有一个能被执行 0为假,非0的任何情况都为真*注:if以及相应的语句块可以单独实现,但else不幸
if和相应的else中间不能有其他语句
**注:结构化编程中,if else for while 后面可以不跟花括号{},如果不跟花括号,就表示关键字后面紧接着的第一条语句是属于这个结构的,后面的都不属于
嵌套形式:
if(表达式1){ if(表达式2){ 语句块1; }else{ 语句块2; } }else{ if(表达式3){ if(表达式4){ 语句块3; }else{ 语句块4; } } } 1.判断表达式1是否成立,如果成立再判断表达式2,表达式2如果成立就执行语句块1,然后跳出所有if...else 2.表达式2如果不成立,则执行语句块2,然后跳出所有if...else 3.表达式1如果不成立则开始判断表达式3,如果表达式3成立则开始判断表达式4 4.表达式4如果成立则执行语句块3,然年跳出所有的if...else 5.表达式4如果不成立则执行语句块4,然后跳出所有的if...else 6.表达式3如果不成立则跳出所有的if...else阶梯形式:
if(表达式1){ 语句块1; }else if(表达式2){ 语句块2; }else{ 语句块3; } "多选一" 1.判断表达式1,如果成立则执行语句块1,然后跳出if...else 2.表达式1不成立则判断下一个表达式2,表达式2如果成立则执行语句块2,然后跳出if..else 3.表达式2也不成立则直接执行语句块3,然后跳出if..else
选择
switch(表达式) //表达式不能为浮点数 { case 常量表达式1:语句块1; ... default:语句块n; } 根据表达式的结果,选择case引导的常量表达式们,谁完全匹配就选择谁的语句块来执行,如果都不匹配则选择default的表达式来执行break continue return break:表示跳出当前的控制结构 continue:表示跳出本次控制(用于循环)(跳过这一次循环) return:表示结束函数
循环
C语言中的循环其实就是在重复做相同或者类似的事情
for while do{} while goto
for
for(表达式1;表达式2;表达式3){ 循环体; } 1.第一次总会执行表达式1 2.判断表达式2,如果表达式2为假,则跳出循环,如果表达式2为真,则执行循环体 3.执行完循环体后,执行表达式3 4.重复第2步嵌套循环:
for(表达式1;表达式2;表达式3){ for(表达式4;表达式5;表达式6){ 循环体; } } 1.执行表达式1 2.判断表达式2,如果表达式2为假,则跳出大循环,如果表达式2为真,则执行第二个for循环 3.执行表达式4 4.判断表达式5,如果表达式5为假,则跳出小循环,如果表达式5为真,则执行循环体 5.执行完循环体后,执行表达式6 6.重复第4步 7.如果表达式5为假,跳出小循环,回到大循环,执行表达式3 8.重复第2步while
while(表达式){ 循环体; } 1.判断表达式是否为真,为真则执行循环体,为假则跳出循环 2.执行完循环体后,再来判断表达式*注:为了实现有限循环,都会把循环条件的改变写在循环体内
do{}while
do{ 循环体; }while(表达式); 1.执行循环体,再来判断表达式 2.表达式为假则跳出循环,表达式为真则再执行循环体*注:和while不一样,do {}while一定会执行一次循环体
**注:do{}while后面是有分号的,但是for和while后面没有
goto
不建议用
强制跳转
数组
逻辑层面:一些相同类型的数据的集合
存储层面:一片连续的存储空间
声明形式
<存储类型><数据类型> 数组名[元素个数]; int array[3];元素个数:表示告诉编译器需要开辟多大的空间
数组的使用
int array[3]; array[0] = 1; array[1] = 10; array[2] = 100; array[3]; //一定是错的 数组名[元素下标]; //表示数组中某个具体的元素(数据) *注:数组的下标总是从0开始,n个元素的数组,最大下标为n-1*注:只要数组和数据类型同时出现在一个语句里面,那么[]里表示元素个数,其他时候都表示下标
**注:数组的下标在使用的时候不能超过最大下标,超过叫做越界(可能会出错,也可能不会出错)
int array[5];
array = {1,2,3,4,5}; //不行
array[5] = 12,3,4,5; //不行
数组下标的使用
int a[5]; int i = 3; a[0] = 100; //一个数值常量可以充当数组下标 a[1+2] = 50; //表达式也可以充当数组下标 a[i] = 1000; //一个变量也可以充当数组下标,这个下标就是变量的内容 a[b[i]]; //也可以 a[2.5]; //不可以*注:只要数组的下标最后能被解释成合理的整数就可以。而我们通常在操作数组时,数组元素特别多,会使用循环来挨个操作数组的元素
数组的初始化
int a[6]={1,2,3,4,5,6}; //完全初始化,从0下标开始依次往后赋值 int a[6]={1,2,3,4}; //部分初始化,从0小标开始依次赋值,未初始化的空间,编译器自动赋值为0 char buf[32]={0}; int a[]={1,2,3,4,5}; 编译器会根据初始化的数据个数来给数组分配相应大小的空间
冒泡排序
int a[]={2,5,9,10,3,7};
for(i=0;i<n;i++){ //用于遍历整个数组的数据(或者确定位置) for(j=i+1;j<n;j++){ //找到合适位置的数据 } }
字符数组
存放字符或者字符串的数组
char a[]={'h','e','l','l','o'}; 占5个字节 //存放字符串 char b[]={"hello"}; 占6个字节,因为以'\0'作为字符串结束标志符 '' 表示单个字符 "" 表示字符串,就算双引号里面只有一个字符,也会添加一个'\0'
二维数组
多个一维数组
声明形式:
<存储类型><数据类型> 数组名[行数][列数]; int a[2][3]; //6个元素,整个数组大小6*sizeof(int)*注:二维数组只是抽象出来有行列,实际在内存中还是线性存储
类似一维数组,不过使用嵌套循环(先循环行数,再循环列数)
二维数组
int a[2][2]={1,2,3,4}; int a[2][2]={{1,2},{3,4}}; //花括号应该成对出现 int a[2][3]={1,2}; //部分初始化 int a[][3]={1,2,3,4};
二维数组的初始化:
字符数组: char a[][5] = {"hello","ok"}; 一共有两行 第一行只存了有hello五个字符,'\0'没有存进去 第二行存了ok两个字符,但是空间还有剩余,所以存了'\0'
指针
内存中每个字节的编号---内存地址
而指针就是地址
指针变量:
<存储类型><数据类型 *> 指针名; 存储类型:就是常见的类型 数据类型:不由本身决定,而是由指针所指向的空间决定 void *表示任意类型的指针,可以存放任意类型空间地址,但是间接运算的时候一定要强制转换类型
int a; int *p; void *q;
指针的使用
char a = 'A'; char *p; p = &a;直接运算:直接通过变量本身得到内容
间接运算:通过指向变量空间的指针间接得到内容
a <==> *p //结果一样
野指针:比如定义的局部指针变量,因为局部变量的值是随机值,所有这个指针变量可能指向任意的地方(可能会出错也可能不会出错)
空指针:指针变量里面存放0这个地址,而0这个地址所表示的空间一定不能被访问,如果使用一定会出错。
大端小端
指针间接运算的时候会根据类型(指针的类型)来运算相当大的空间
大端:通常用于网络架构中,powerpc、mips等
低字节的数据存放在高地址中,高字节的数据存放在低地址中
小端:常用的机器设备,x86,ARM等
地字节的数据存放在低地址中,高字节的数据存放在高地址中
其他
指针变量的大小:恒定的
32位系统下,占4个字节
64位系统下,占8个字节
指针的初始化
int a; int *p = &a; int *p , q; //p是指针,但q是普通变量
指针的运算
算术运算
\+ -:++ -- +1和++是一个意思 int a = 10; a++; int *p = &a; p++; //表示p后面的空间移动,去指向一个高地址 //指针的假发(减法)偏移,并不是单纯的地址偏移,而是空间偏移 p ==> 0x123; //p为int * p+1 ==> 0x124; //错的 p+1 ==> 0x127; //对的 指针的加法: +1或者++:就是往高地址偏移1个数据类型的空间,偏移的字节量:sizeof(数据类型) +n:就是往高地址偏移n个数据空间,偏移的字节量:n * sizeof(数据类型)
乘法、除法以及两个指针变量相加是毫无意义的 但是 两个相同类型的指针相减有意义: 两个同类型指针相减可以得到相差多少个这种类型的空间(通常会用在数组里面) 字节量偏移:(p的地址值 - q的地址值) 空间量偏移:(p的地址值 - q的地址值) / sizeof(数据类型)
关系运算
比较两个或者多个指针的位置关系
p > q; //p是否在高地址(相对q) p < q; //p是否在低地址(相对q) p == q; //p是否和q同时指向同一个空间
变量
全局变量:声明在所有函数体外的变量
局部变量:声明在函数体内的变量,如果不初始化,那么局部变量的默认值是随机的
变量的声明形式:
<存储类型><数据类型>名字;
char var;
存储类型:auto register
static:修饰局部变量的时候,生命周期会延长,作用域不变
修饰全局变量的时候,生命周期不变,作用域会被限制
修饰函数的时候,和全局变量一样
extern:引用外部的定义
int main() { int a; //在栈区中开辟一个4个字节大小的空间,用于i存放整形数据,局部变量 }
运算符
算术运算符:
+ - * / % int a; a = 1+2; a = 10/3; //整数除以整数就算有小数也会省略赋值运算符:
= 把右边的内容赋值给左边 a = b = c = d; a = (1,2); //最后结果为2关系运算符:
> < == >= <= != 要么为真要么为假 通常0表示假1表示真逻辑运算符:
|| && ! ||:逻辑或,有真则为真,全假才为假 &&:逻辑与,有假则为假,全真才为真 !:逻辑取反 注意短路原则位运算符:
<< >> | & ~ ^ <<:把数据的二进制形式往左移动1位,增大这个数,低位添加一个0 >>:把数据的二进制形式往右移动1位,减少这个数,高位添加一个0 |:把数据的二进制形式某一位进行相或 &:把数据的二进制形式某一位进行相与 ~:按位取反三目运算符:
表达式1? 表达式2:表达式3 if(a<b) return; else return; return (a<b)?0:1sizeof运算符:
求字节大小,可以求变量,也可以求数据类型 sizeof(x);
类型转换
隐式转换:编译器自动帮助运算的变量进行同步类型 int a = -6; unsigned int b = 20; 有符号往无符号转,低精度往高精度转 显示转换(强制类型转换):需要在要转换的前面添加括号(数据类型) void *p = &a; *(int *)p;
输入输出
格式化输入输出:行缓存
scanf("",空间地址); printf("",空间名字); %d %c %s %p %u %e %f %x %o %ld \t \n \八进制 转换 ASCII表对应的字符
字符输入输出:
getchar() putchar()
字符串输入输出:
gets(); //比较危险,gets的括号里只有存放数据的地址,没有规定要输入多少数据(容易超过打大小) fgets(void *p,size_t count, FILE *stream); stream==> stdin puts();
指针数组与数组指针
指针数组
本质是数组,修饰的词是指针,就表示这个数组用于存放指针类型
声明形式:
<存储类型><数据类型 *>名字[元素个数]; int *p[3]; //p数组有三个空间,每个空间用于存放int*型的指针总结:指针数组就是一些相同类型的指针变量的集合,每个元素空间都是一个单独的指针变量
10.1.1指针和数组的关系
普通指针和一维数组的关系 int a[10]; int *p = a; p++;
数组指针
本质上是指针,修饰词是数组,专门用来指向数组的指针
声明形式:
<存储类型><数据类型>(*名字)[元素个数]; int (*p)[3]; int a[3][4]; int (*ptr)[4] ptr = a;
多级指针
指针变量也是变量空间,也有地址,也能被另一个指针所存放
二级指针:指向指针的指针
int a = 10; int *p = &a; int **q = &p; *q得到p的内容,这个时候的内容是int *
函数
函数就是特定功能的代码块,程序所执行最小单位就是函数模块
函数的声明:
<存储类型><数据类型>函数名(参数列表); 函数的定义:<存储类型><数据类型>函数名(参数列表) { 函数体; 返回值; }
存储类型:经常用extern,一般来说我们会声明函数在头文件里面,定义函数在源文件(一般不和main在一起)
数据类型:不由函数本身决定,而是由返回值的类型决定
bool:布尔类型,返回真或假
void:表示函数没有返回值
返回值:就是函数执行的结果(告诉主动调用这个函数的人一个结果)
参数列表:这个函数需要哪些类型的数据来处理
函数的调用
形式:
函数名(参数列表); _Print();
函数的参数传递
按值传递:把变量名字所表示的内容拷贝到函数的形参空间,所有的操作理论上在操作形参空间 按值传递的局限:改变不了实参本身,所改变的都是形参 按地址传递:把实参的地址拷贝到形参空间,形参应该为指针类型 如果要改变实参本身,只需要去操作指针就可以了
char a[] = {"hello"}; //打印字符串的特点,也是必须的一部:告诉printf字符串的起始地址在哪里 printf("%s",a);
1.传递变量的时候,只需要操作变量或者变量的地址就可以了 函数的参数类型也很简单,只需要对应就可以了 2.给函数传递数组的时候: 数组的名字是一个指针,通常函数的参数需要接受数组的话,会定义一个指针变量来接受,用这个指针变量是无法得知数组的空间大小。(应该连同数组)
数组的名字和普通的指针变量是两回事,虽然数组的名字可以给指针变量赋值(内容上两者可以一模一样),但是属性上一个是表示数组,一个是表示变量(只能存放地址) int a[3]; int *p; p = a; sizeof(a); //其实是在求数组名字表示的这个地址指向的空间的大小 sizeof()
const
const表示常量(用于修饰一个变量)
在一个变量声明阶段就把它声明为不可更改的类型(内容不能变化)
const int *p; //表示p所指向的空间的内容不能变(通过指针是不能改变) int const *p; //同上 int * const p; //表示p所指向的空间不能变(指针本身不能被改变) const int * const p; //p的指向和指向的空间内容都不能变注:关注const 和 变量名之间有没有任何符号,如果没有就表示指向不能变,如果有就表示指向的空间内容不能变。
字符串处理函数
strlen:计算字符串的长度,不包含'\0'
size_t strlen(const char *s); 返回值:字符串的有效字符个数 s:所表示的字符串的首地址 char buf[] = {"hello"}; strlen(buf);
strcat:链接两个字符串,把src所指向的字符串连接到dest所指向的后面
char *strcat(char *dest,const char *src); 返回值,返回已经连接好的字符串的首地址(dest) dest:需要在末尾被添加字符串的指针 src:要连接在另一个末尾的字符串的指针注:dest所表示的空间一定要足够大(因为src所表示的内容要拷贝到dest
原本字符串的后面)容易越界
strcpy:拷贝字符串,把src所表示的字符串拷贝到dest空间里面
char *strcpy(char *dest,const char *src); 返回值,返回已经拷贝好的字符串首地址(dest) dest:表示拷贝完成后的字符串首地址 src:表示拷贝内容的字符串首地址注:strcpy并不是把dest里面的内容清空,而是根据src的内容来直接覆盖,如果src的长度没有dest原来的字符串长,那么原来的部分内容还是会保留在dest里面(只是src拷贝完后会有一个'\0'来打断字符串)
(64位操作系统,编译器版本更高)
strcmp:
int strcmp(const char *s1,const char *s2); 如果两个字符串一样,返回值为0 如果是s1的字符串某一位的字符比s2字符串的相应的位大,那么返回两个字符相差的ASC码(正数) 如果是s1的字符串某一位的字符比s2字符串的相应的位小,那么返回两个字符相差的ASC码(负数)注:两个字符串都是从第一个字符串开始,挨个比较,只要第一次遇见不一样的地方,那么久结束比较并返回差值
注:如果是32位操作系统,编译器版本更低,那么返回值只有三个(0,1,-1)
指针函数
函数的返回值只要是个地址的函数,都叫做指针函数
char *strcat(char *s1,char *s2)