目录
本文主要是先带大家全局的认识一下C语言,将C语言的主要的东西都看看,了解一下,对C语言先产生一个认识,每个知识点后面都会多带带写博客详细介绍。
C语言是一门通用的计算机编程语言,广泛应用于底层开发,C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程
语言,保持着良好跨平台的特性。
由于C语言的各大优点使得各大开发厂商纷纷使用,并且各个厂商都有了自己的C语言,这就使得各厂商的C语言语法出现差异,为了避免这种情况,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。
并且C语言是一门面向过程的编程语言,编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。其中MSVC便是微软的C语言编译器,VS2019中的C语言便是MSVC编译器。编译环境的详细搭建步骤我也已经写了,请点击这里查看C语言编译环境的搭建。
语言 | 用途 | 举例 |
人类的语言 | 人与人之间交流 | 汉语,英语 |
计算机语言 | 人与计算机交流的语言 | C/C++/JAVA |
C语言广泛应用于底层的软件开发
#include int main(){ printf("Hello world!"); return 0;}
一个C语言代码中必须包含一个main函数--主函数,main函数是程序的入口,有固定写法。要注意的是一个工程中只能有一个main函数。
main前面的int表示函数返回类型为整型,左花括号表示函数开始,右花括号表示函数结束;花括号所包含的部分叫做函数体,为该函数所要实现的逻辑功能语句。return 0表示返回值是0,0为整数,与前面的int相呼应。printf----print function----打印函数,而printf属于库函数,是C语言自身提供的函数,库函数的使用必须要引用头文件,所以使用了#include
在菜单栏中有 调试--开始执行(快捷键Ctrl+F5)
我们用一段代码来验证一下
#include int main(){ printf("Hello world!"); return 0;}int main(){ printf("Hello world!"); return 0;}
编译器报错
如果是在同一个工程中不同的.c文件中呢,也是一样的,同一个工程中只能有一个main函数。
我们前面说过,main函数是程序的入口,如果一个工程出现多个main函数,那么这个程序到底从哪里开始执行,从哪个main函数进去是不确定的。
我们在生活中经常会用到各种各样的数据,例如年龄,体重,价格等等,而不同的数据的类型也是不一样的,比如年龄是整数,体重是小数。
我们写程序,写软件也是为了能够解决生活中的问题,描述生活中的问题,所以C语言它有各种数据类型。
char | 字符数据类型 | 字符 |
short | 短整型 | 整数 |
int | 整型 | |
long | 长整型 | |
long long | 更长的整型 | |
float | 单精度浮点数 | 小数 |
double | 双精度浮点数 |
我们的生活中本来就有很多种数据类型,在写代码的时候,我们选择合适的数据类型去创建变量,解决问题,使得空间利用率更高,并且更加丰富的表达生活中的各种值。
C语言中有一个关键字sizeof可以用来计算各种变量,数据类型的大小
如下代码:
#include int main(){ printf("%d/n", sizeof(char)); printf("%d/n", sizeof(short)); printf("%d/n", sizeof(int)); printf("%d/n", sizeof(long)); printf("%d/n", sizeof(long long)); printf("%d/n", sizeof(float)); printf("%d/n", sizeof(double));}
运行结果:
(注意:sizeof计算出来的结果单位是字节)
我们会发现int为整型,而long是长整型,结果运行结果中int和long的大小一样,这是怎么回事呢?注意在这里C语言标准规定,sizeof(int)<=sizeof(long),并且sizeof(long)<=sizeof(long long)
在32位平台sizeof(long)大小为4个字节,而在64位平台,sizeof(long)大小为8个字节
选择合适的数据类型,如下代码:
int main(){ //这里创建一个年龄的变量 //short的范围为-32768~32767,足够表示年龄 short age = 18; //创建一个变量表示体重 double weight = 58.9; return 0;}
变量:生活中有些值是可变的(eg.年龄,身高,体重等),C语言中用变量来表示
常量:有些值是不变的(eg.身份证号,血型等),C语言中用常量来表示
我们通过这段代码来了解全局变量与局部变量
#include //全局变量int i = 20;int main(){ //局部变量 int i = 10; printf("%d/n", i); return 0;}
运行结果:
那么这里为什么运行结果是10而不是20呢?
有几个点需要注意:
#include int main(){ int n1 = 0; //定义整型变量n1,n2和num并初始化为0 int n2 = 0; int sum = 0; printf("请输入n1和n2/n"); //提示用户输入 scanf("%d%d", &n1, &n2); //输入想要进行运算的两个数 sum = n1 + n2; //将n1和n2相加并赋值给sum printf("sum=%d/n", sum); //打印sum的值 return 0;}
说明:
scanf函数:代码中用到scanf函数,属于库函数,也是要引头文件
注意事项:
printf函数:%d表示以整数形式进行打印。
这两个函数中,其中格式控制字符串用于指定格式。格式控制串可由格式字符串和非格式字符串两种组成。格式字符串是以%开头的字符串,在%后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等,如下所示:
%d //打印整型
%c //打印字符
%f //打印浮点数
%p //以地址的形式打印(打印地址)
%x //打印16进制整数
%o //打印8进制整数
作用域(scope):这个变量哪里可以使用,哪里可以起作用,哪里就是它的作用域
生命周期:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
可以通过以下代码的对比来深刻理解作用域
代码1:
#include int main(){ { int n = 10; printf("n=%d/n", n); } return 0;}
运行结果:
代码2:
#include int main(){ { int n = 10; //printf("n=%d/n", n); } printf("n=%d/n", n); return 0;}
运行结果 :
分析:离int n = 10;最近的花括号所包含的里面就是变量n的作用域,它的地盘,而一但出了花括号,它就不起作用了。所以就会报错。
代码3:
#include int a = 10; //全局变量void test() //这里定义一个函数进行测试{ printf("test-->a=%d/n", a);}int main(){ printf("a=%d/n", a); test(); return 0;}
运行结果:
从代码3就可以看出全局变量的作用域更广,即整个工程。
C语言中的常量和变量的定义的形式有所差异
C语言中的常量分为以下几种:
通过以下代码来理解这几种常量
代码1:
1.字面常量
#include int main(){ //1.字面常量 55; 9.8; "b"; //直接写出来的常量就被称为字面常量 return 0;}
代码2(与代码3进行对比):
#include int main(){ int a = 10; printf("a=%d/n", a); a = 20; printf("a=%d/n", a); return 0;}
运行结果:
代码3:
2.const修饰的常变量
#include int main(){ //2.const修饰的常变量 const int a = 10; //用const进行修饰,使其成为常变量 printf("a=%d/n", a); a = 20; printf("a=%d/n", a); return 0;}
运行结果:
通过代码2和代码3的对比即可发现,a本身为变量,但被const修饰之后,它本质上还是一个变量,但它又具有了常属性,不能改,在使用常量的时候是不能用const修饰的常变量的,但可以用它去表示一个不能变的量(具备常属性的一个变量)
比如以下情况:
在创建数组的时候,数组的长度应该是指定的一个确定的常数,虽然n被const修饰之后具有了常属性,但它本质上还是一个变量,不能作为数组长度来使用。
3.#define定义的标识符常量
代码1:
代码2:
可以看到这(AGE)也是不能被修改的,因为它是一种常量
4.枚举常量
在生活中有很多的取值是可以一一列举的
eg.
性别:男,女,保密
三原色:红,绿,蓝
星期:1,2,3,4,5,6,7
如下代码:
注意:枚举常量也同样是不能改变的,从运行结果就可看出,枚举常量它是有具体的值的,eg.RED值为0,GREEN值为1,BLUE值为2。
我们首先来认识一下字符串,前面我们写过这样一个代码
#include int main(){ printf("hello world!/n"); return 0;}
在printf函数里面被" "包含的部分即为字符串(这里的/n表示换行的意思)
以下几种情况均为字符串
"abcde"
"b"
"" //空字符串
这种由双引号引起来的一串字符称为字符串字面值,简称字符串
注意:字符串的结束标志是一个/0 的转义字符。在计算字符串长度的时候/0 是结束标志,不算作字符串内容。通过以下代码来理解:
#include int main(){ char arr1[] = "qwert"; char arr2[] = { "q","w","e","r","t" }; printf("%s/n", arr1); printf("%s/n", arr2);}
大家可以想想这段代码打印的结果是什么呢?
结果如下:
发现arr1正常打印,但arr2的打印结果为什么这么奇怪呢?
接下来我们仔细分析一下:
在VS2019编译器中按F10进行调试,然后打开监视器窗口:
可以在监视器窗口中看到arr1和arr2中存的内容
通过这个我们可以发现:arr1中有/0,所以在打印过程中遇到/0停了下来;arr2中没有/0,打印完qwert之后还未停下,继续往后打印,而后面都是随机值,所以就打印出来烫烫烫,/0本身的值为0,所以在往后打印过程中恰好有一个值为0,遇到结束标志,打印结束。
那么我们就可以手动的给arr2后面添加/0或者0来让它具有结束的标志,不会出错打印随机值。如下代码:
我们这里再介绍C语言提供的一个库函数strlen--string length--字符串长度,这是用来计算字符串长度的,遇到/0结束,不计算/0;头文件为
我们会看到,arr1里卖弄一共5个字符,长度为5,没有问题,但这个arr2由于没有/0作为结束标志,后面全部都是随机值,所以strlen一直往后计算,直到遇到第22个值为0,才结束计算 ,所以它计算出来的21本身就是一个随机值。(同样可以后面添加"/0"或者0来解决)
这里其实我们也可以通过关键字sizeof来计算,但要注意的是sizeof会将"/0"计算进去。如下代码及结果:
前面我们见到过"/n","/0"这样的字符,都是转义字符
我们可以通过以下代码来体验一下:将c:/code/test.c打印在屏幕上,以下代码到底能不能实现?
代码0:
通过运行发现打印的并不是我们想要的结果,这个时候就有了转义字符(转变它原来的意思)的概念。通过以下两段代码对比理解一下:
代码1:
代码2:
通过对比我们就可以发现,在n前面加上/后,它就已经不是单纯的n了,而有了其他的作用(换行),代码保存路径以及请按任意键关闭窗口与hello之间有个空行,而代码1没有/n,所以就没有空行。所以在这里/n就是一个转义字符了。回过头看,代码0里面的/t也是一个转义字符了,即水平制表符。
下来我们可以看看都有哪些转义字符:
转义字符 | 含义 |
/? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
/" | 用于表示字符常量" |
/“ | 用于表示一个字符串内部的双引号 |
// | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
/a | 警告字符,蜂鸣 |
/b | 退格符 |
/f | 进纸符 |
/n | 换行 |
/r | 回车 |
/t | 水平制表符 |
/v | 垂直制表符 |
/ffffd | ffffd表示1~3个八进制的数字。 如: /130 X |
/xdd | dd表示2个十六进制数字。 如: /x30 0 |
对以上的转义字符解释:
代码1:打印字符"a"
发现成功打印出来字符"a"
代码2:打印字符单引号"""
#include int main(){ printf("%c/n", """); return 0;}
运行程序发现程序报错,那么这又是什么原因呢?
就是因为三个单引号放在一起,自动的前两个单引号结合,后面单引号落单了,所以就会报错,这个时候就可以使用转义字符/" ,使它成为一个普通的字符单引号,字符/"也是如此,不在啰嗦。如下代码:
3.// 双斜杠这个转义字符其实它的用途就是我们刚才的代码0,我们想要将代码路径c:/code/test.c打印到屏幕上,但是里面的/t
是一个转义字符,现在我们不想让它转义,就想让他打印出来/t,我们就可以使用//将它再次转义,使/t 里面的斜杠就只是一个斜杠,如下:
4./t 水平制表符,相当于起到了电脑键盘table键的作用
5.接下来我们来说说最后两个转义字符/ffffd和/xdd ,涉及到8进制和16进制
平时我们用到的10进制数就是由0-9这10个数构成的,那么8进制就是由0-7这8个数构成(16进制就是由0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F来表示,A--10,B--11,C--12,D--13,E--14,F--15),在/后面跟3个8进制数,eg./061
运行以下代码看看结果
可以看到结果是1,但是8进制数061的10进制数也不是1呀,为什么结果是1呢?因为在这里它是一个字符,将8进制数转化为10进制数49(ASCII码值)之后所对应的那个字符是1。
再详细说说,我们的键盘上可以敲出来一系列的字符,eg.@#$%^&*,但是计算机只能识别二进制呀,所以人们就给字符编了统一的号码,eg. a--97,b--98………将这种编码称为ASCII编码(有专门的ASCII码表),而字符"1"的ASCII值为49,转化为8进制也就是061。
/xdd 这个转义字符我们就不再啰嗦,和/ffffd同样的道理
下面来一道笔试题进行练习
//程序打印的结果是什么?#include int main(){ printf("%d/n", strlen("abcdef")); printf("%d/n", strlen("c:/test/328/test.c")); return 0;}
这段代码的运行结果是什么呢?可以先想想, 第一个printf的答案比较简单,就是字符串的长度6(注意strlen函数不计算/0),而第二个printf的答案呢,18? 12?还是说14? 这几个答案都不对。
我们来分析一下,在"c:/test/328/test.c"这个字符串里面,首先/t是转义字符,作为一个整体算作一个字符,/328,这里面的8已经超出了8进制的范围(8在这里本身就是一个坑),所以应该将/32作为一个整体,16进制,所以第二个printf打印的结果应该是14
注意:
C语言风格的注释:/*xxxxxx*/存在缺陷,不能嵌套注释,嵌套注释就会出问题
C++风格的注释://xxxxxxx,可以注释一行,也可以注释多行
我们的生活中总是面临着各种各样的选择,怎么选就看自己了
通过以下代码来体验一下:
这段代码用到了一个if else语句,当if后面圆括号里面的判断条件为真时,执行if下面的语句,当条件为假时,执行else后面的语句
在我们色生活中也会有很多的事情都在重复,eg.起床,干饭,学习,睡觉
C语言里面有3种循环
通过以下代码来体验一下
在数学中我们经常和函数打交道,eg. f(x,y)=x+y,这是一个二元函数,该函数有两个参数(变量),x和y,那么其实C语言里面的函数和这个也是非常相似的。通过以下代码来了解一下
我们之前计算加法都是直接sum=x+y这样来算的,但在这段代码中我们定义了一个函数Add来计算加法。首先创建了两个变量x,y和z,调用Add函数,并将Add函数的返回值赋给z,最后将z的值打印了出来。
重点再来看一下Add函数,前面的int表示该函数的返回值为int类型,后面括号里面的int x,int y表示Add函数的两个参数均为int类型。花括号里面即为函数体,创建了临时变量z来接受x+y的值,并在最后将作为返回值返回
函数的特点:简化代码,代码复用
数组其实就是一组数。比如我们平时要存放一个数10,那么只需要int a = 10;就可以完成;那如果要存放1,2,3,4,5这5个数字呢,不可能创建5个整型变量来存放吧,这样创建和使用都会很麻烦,所以这个时候就有了数组的概念----一组相同类型元素的集合。
int arr[10] = { 0,1,2,3,4 };
这个代码中就是定义了一个数组,int表示数组内的元素类型为整型,arr是数组名,[10]里面的10表示这个数组最多放10个元素,后面花括号里面是对这个数组进行了初始化,前五个元素分别初始化为了0,1,2,3,4,而剩下的5个元素会默认初始化为0。可以打开监视器来看看:
关于数组:
如果要将数组中的某个元素打印出来呢?代码如下:
全部打印呢?
代码中我们通过一个while循环来实现打印数组中的全部内容(每次打印一个元素)
+ - * / %
>> <<
& ^ |
= += -= *= /= &= ^= |= >>= <<=
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
&& 逻辑与
|| 逻辑或
exp1 ? exp2 : exp3
exp1, exp2, exp3, …expN
[] () . ->
这些操作符我们后面还会继续讲,这里先简单了解一下
我们先来了解一下 / 这个操作符,通过以下代码来体验以下:
#include int main(){ printf("%d/n", 7 / 2); return 0;}
那么这段代码的运行结果是什么呢? 3.5?
运行结果:
发现运行结果是3,这是为什么呢?
来分析一下,C语言里面的 / 和我们平时数学中的除号还是有区别的,这里是整除求商的意思,7除以2本来应该是3.5,但这里是整除,商只有3,没有5,所以结果为3。那么如果我们想要得到3.5应该怎么做呢?只需要让 / 两边的数字有一个是小数即可,如下代码:
那么有没有哪个操作符是用来整除求余的呢,肯定是有的------%取模操作符,如下代码:
7对2整除的余数便是1
再来看看移位操作符:右移操作符>> 和左移操作符 << 请看以下代码:
#include int main(){ int a = 8; printf("%d/n", a >> 1); return 0;}
这里的a>>1表示将a的值向右移动一位,那么移动一位到底移的是什么位呢? 移的是二进制位,那么我们在这里将a先写成二进制形式为1000,而这里的a又是一个整型,4个字节----32个比特位,准确来写应该是00000000000000000000000000001000,这里将a向右移动 一位我们通过下图来更深刻的理解:
可以看到右移之后1的权重降低,值变为4,可以通过运行来验证一下
左移同样也是这样,我们通过后面的博客细细道来。
位操作符:
& 按位(二进制位)与
| 按位(二进制位)或
^ 按位(二进制位)异或
同样通过以下代码来体验一下:
#include int main(){ int a = 5; int b = 3; int c = a & b; printf("%d/n", c); return 0;}
通过下图来理解
所以a&b的结果就是1,a|b为7,a^b为6
再看赋值操作符
#include int main(){ int a = 10; a = a + 3; printf("%d/n", a); return 0;}
这里a本来是10,然后a=a+3就是给a加3之后放到a里面去,a就变成了13。并且这里用a+=5也是同样的效果
单目操作符
前面我们看到的+,它就有两个操作数,a+b,必须有两个操作数,而单目操作符就是只有一个操作数
逻辑反操作 ! ,这个操作符它只关注操作数的真假
C语言里面是如何区分真假的呢?
0----表示假
非0----表示真
通过下面的代码的结果来对比一下
下一个操作符 ~ 我们先来了解一下原码,反码和补码的概念
比如int a = -1,我们将十进制数字转化为二进制数字得到的是他的原码,通过图来理解
注意:
以下代码
#include int main(){ int a = 0; //分析: //a的原码:00000000000000000000000000000000 //补码: 00000000000000000000000000000000 //按位取反 11111111111111111111111111111111 //反码; 11111111111111111111111111111110 //原码: 10000000000000000000000000000001 //所以结果应该是-1 printf("%d/n", ~a);}
这里再加一个小的知识:
在C语言里面0分为+0和-0
+0
原码:00000000000000000000000000000000
反码:00000000000000000000000000000000
补码:00000000000000000000000000000000
-0
原码:10000000000000000000000000000000
反码:11111111111111111111111111111111
补码:10000000000000000000000000000000
自增自减操作符++,--
通过以下代码来体验一下
#include int main(){ int a = 0; int b = a++; //后置++,先使用a的值,然后再让a加1 int c = 1; int d = ++c; //前置++,先让c加1,然后再把c的值赋给d printf("a=%d,b=%d/n",a,b); printf("c=%d,d=%d/n", c, d);}
强制类型转换操作符
如下代码:
3.14是double类型的,将double类型的数据赋给int类型,我们发现编译器报了一个警告
那么我们应该怎么解决呢? 这个时候就可以用强制类型转换
#include int main(){ int a = (int)3.14; return 0;}
关系操作符
关系操作符其实就是用来比较大小,这里主要再来强调一下判断相等与不相等,用的是==而不是=
以下情况我们可能后面稍不注意就会犯这种错误
int main(){ int i = 1; if (i = 0) { printf("hello"); } return 0;}
这里会不会把hello打印出来呢? 答案就是:不会打印
原因:if后面的条件判断用了一个赋值,这里不是在判断i是不是等于0,而是将0赋给i,然后i是0条件为假,就不会打印,应该要用==
逻辑操作符
逻辑与 && 表示的是如果两边的值都为真,那么结果为真,如果其中有一个为假,那么结果为假
罗技或 || 表示如果两边有一个值为真,那么结果为真,如果两个都为假,那么结果为假
如下代码示例:
int main(){ int a = 5; int b = 3; int c = 0; int d = 0; printf("%d,%d/n", a && b, a && c); printf("%d,%d/n", a || b, d || c);}
条件操作符
这里的条件操作符有三个操作数,所以也叫三目操作符。exp1 ? exp2 : exp3
含义:表达式1的结果如果为真,就执行表达式2,如果表达式1的结果为假,就执行表达式3
我们之前写代码求两个数的最大值都是通过if语句来判断,现在我们完全可以通过条件操作符来计算,可以极大的简化代码。
#include { int a = 5; int b = 3; int max = a > b ? a : b; printf("%d/n", max); return 0;}
逗号表达式
逗号隔开的一串表达式。逗号表达式的结果从左向右依次计算,但表达式的结果是最后一个表达式的结果
#include int main(){ int a = (1 + 2, 2 - 3, 3 + 5); //表达式里面的从左到右以此计算,但最终结果是最后一个表达式的结果 printf("%d/n", a); //结果应该是3+5==8 return 0;}
函数调用操作符
我们在每次调用函数的时候都必须要有函数调用操作符(),圆括号里面放参数,来传参
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
auto关键字平时都是省略的,局部变量都是自动创建,自动销毁的,所以C语言中的局部变量都是自动变量
auto int a=10; //这里的auto平时都是省略不写的
break 终止循环/switch
case switch语句
const 常变量
continue 继续循环
default switch
enum 枚举
extern 声明外部符号
goto 跳转(不建议使用)
register 寄存器关键字
static 静态
(1.修饰局部变量,改变的是局部变量的生命周期,和程序的生命周期一样
2.修饰全局变量,改变了它的作用域,使这个变量只能在自己所在的源文件内部使用
3.修饰函数,改变了这个函数的使用范围,这个函数只能在自己所在的源文件内部使用)
typedef 类型重定义
union 联合体/共用体
volatile 比较少见
这些关键字,我们后面都会讲到。
注意:在创建变量的时候变量名不能是关键字
通过以下代码来了解一下:
#include #define PI 3.14int main(){ double a = PI; printf("%lf/n", a);}
这里的PI就是属于标识符常量
这里我们来写一个加法的宏来体验一下:
<文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/119681.html
上次给大家分享了一个springboot+vue的校园招聘系统,视频教程加项目源码,都是开源的,应该说很香了,今天再给大家分享一个不错的springboot的项目。 老规矩,开源,开源,开源!!! 金九银十来了,小伙伴们,冲啊!前面已经整理了很多的面试题,拿去学习吧! 1,❤️爆肝!整理了一周的Spring面试大全【含答案】,吊打Java面试官【建议收藏】!❤️ 2,❤️肝完了,一天掌握数据...
文章目录 强烈推荐系列教程,建议学起来!! 一.pycharm下载安装二.python下载安装三.pycharm上配置python四.配置镜像源让你下载嗖嗖的快4.1pycharm内部配置 4.2手动添加镜像源4.3永久配置镜像源 五.插件安装(比如汉化?)5.1自动补码神器第一款5.2汉化pycharm5.3其它插件 六.美女背景七.自定义脚本开头八、这个前言一定要看九、pyt...
人生苦短,我用Python 开发环境搭建安装 Python验证是否安装成功安装Pycharm配置pycharm 编码规范基本语法规则保留字单行注释多行注释行与缩进多行语句数据类型空行等待用户输入print输出 运算符算术运算符逻辑运算符成员运算符身份运算符运算符优先级 字符串访问字符串中的值字符串更新合并连接字符串删除空白startswith()方法endswith()方法字符串格式化...
阅读 1314·2023-04-26 01:28
阅读 2064·2021-11-08 13:28
阅读 2313·2021-10-12 10:17
阅读 2279·2021-09-28 09:46
阅读 4138·2021-09-09 09:33
阅读 3717·2021-09-04 16:40
阅读 1075·2019-08-29 15:21
阅读 2687·2019-08-26 17:17