Linux基础、C基础

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:1

sizeof运算符:

求字节大小,可以求变量,也可以求数据类型
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)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值