c语言笔记(翁凯老师)

c语言

嵌入式阅读 结合关系一般自左向右,单目+-和赋值=自右向左\这样的表达式太复杂,不容易阅读和理解

#include <stdio.h>

在 C 语言中,sizeof () 是一个判断数据类型或者表达式长度的运算符。

整数类型

char:一字节 8比特

short: 2字节

int:取决于编译器CPU,通常的意义是一个字

long:取决于编译器,通常是两个字

longlong

一台计算器的字长是指当前计算器reg(寄存器)的宽度

寄存器一次可以处理的数据=int 一个字

int就是用来表达寄存器的

如何表示负数

二进制负数

一个字节可以表达的数:

00000000-11111111(0-255)

三种方案:

1,仿照十进制,有一个特殊的标志表示负数

  1. 取中间的数为0,如1000000表示0,比它小的是负数,比它大的是正数
  2. 补码

补码:对于-a,其补码就是0-a,实际上是2的n次方-a,n是这种类型的位数

补码的意义就是拿补码和原码可以加出一个溢出的

整数的输入输出

只有两种形式:int或long long

%d:int

%u:unsigned

%ld:long long

%lu:unsigned long long

一个以0开始的数字字面量是8进制

一个以0x开始的数字字面量是16进制

16进制很适合表达二进制数据,因为4位二进制正好是一个16进制位

8进制的一位数字正好表达3位二进制

因为早期计算机的字长是12的倍数,而非8

带小数点的字面量是double而非float

float需要用f或F后缀来表明身份

*浮点数内部表达

浮点数在计算时是由专用的硬件部分实现的

计算double和float所用的部件是一样的

^字符类型

char是一种整数,也是一种特殊的类型:字符.这是因为:

用单引号表示的字符字面量:a

‘’也是一个字符

printf和scanf里用%c来输入输出字符

*逃逸字符

用来表达无法印出来的控制字符或特殊字符,它由一个反斜杠\开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符

不同的shell做出不同的反应

||优先级大于&&

count[x]++;

*取地址运算

sizeof

是一个运算符,给出某个类型或变量在内存中所占据的字节数

运算符&

·scanf(%d,&i);里的&

·获得变量的地址,他的操作数必须是变量

指针

就是保存地址的变量

int*P=&i

变量的值是内存的地址

·普通变量的值是实际的值

·指针变量的值是具有实际值的变量的地址

访问那个地址上的变量*

* 是一个单目运算符,用来访问指针的值所表示的地址上的变量

·可以做右值也可以做左值(可以放等号两边)

·int k=*p;

·*p=k+1

^指针的使用

·交换两个变量的值

 

·函数返回多个值,某些值就只能通过指针返回

·传入的参数实际上是需要保存带回的结果的变量

函数返回运算的状态,结果通过指针返回

常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:

-1或0

但是当任何数值都是有效的可能结果是,就得分开返回了

·后续的语言(c++,java)采用了异常机制来解决这个问题

*指针最常见的错误

·定义了指针变量,还没有指向任何变量,就开始使用指针

传入函数的数组成了什么?

·函数参数表中的数组实际上是指针

·sizeof(a)==sizeof(int*)

·但是可以用数组的运算符[]进行运算

数组变量是特殊的指针

·数组变量本身表达地址所以

·int a[10];int*p=a;//无需用&取地址

·但是数组的单元表达的是变量,需要用&取地址

·a==&a[0]

·[]运算符可以对数组做,也可以对指针做:

·数组变量是const的指针,所以不能被赋值

·int a[]<==>int *const a=.....

C语言const的用法详解,C语言常量定义详解 (biancheng.net)

判断哪个被const了的标志是const在*的前面还是后面

^保护数组值

·因为把数组传入函数时,传递的是地址,所以那个函数内部可以修改数组的值

·为了保护数组不被函数破坏,可以设置参数为const

·int sum (const int a[],int length);

·给一个指针加1表示要让指针指向下一个变量

int a[10];

int*p=a;

*(p+1)-->a[1]

·如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义

*p++

·取出p所指的那个数据来,完事之后顺便把p移到下一个位置去

·*的优先级虽然高,但是没有++高

·常用于数组类的连续空间操作

·在某些CPU上,这可以直接被翻译成一条汇编指令

0地址

·当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址

·所以你的指针不应该具有0值

·因此可以用0地址来表示特殊的事情

·返回的指针是无效的

·指针没有被真正初始化(先初始化为0)

·NULL是一个预定定义的符号,表示0地址

·有的编译器不愿意用0来表示0地址

指针的类型

·无论指向什么类型,所有的指针的大小都是一样的,因为都是地址

·但是指向不同类型的指针是不能直接互相赋值的

·这是为了避免用错指针

指针类型转换

·void*表示不知道指向什么东西的指针

·计算时与char*相同(但不相通)

·指针也可以转换类型

·int*p=&i;void*q=(void*)p;

·这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量

·我不再当你是int,我认为你就是个void!

size_t类型表示c中任何对象所能达到的最大长度,它是无符号整数.

字符串

·以0(整数0)结尾的一串字符

·0或\0是一样的,但是和0不同

·0标志字符串的结束,但它不是字符串的一部分

·计算字符串长度的时候不包含这个0

·字符串以数组的形式存在,以数组或指针的形式访问

·更多的是以指针的形式

·string.h里有很多处理字符串的函数

字符串变量

·char*str=hello;

·char word[]=Hello;

·char line[10]=Hello;

·Hello会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0

·两个相邻的字符串常量会被自动连接起来

·C语言的字符串是以字符数组的形态存在的

·不能用运算符对字符串做运算

·通过数组的方式可以遍历字符串

·唯一特殊的地方是字符串字面量可以用来初始化字符数组

%*c表示跳过这个字符

%作为引导符,控制输入输出的格式.

%s表示输出字符串形式

%f表示输出为浮点型数据

%o表示以8进制形式输出整数

%d表示输出整形数据

%ld表示输出为长整型数据

%u表示输出格式为无符号数据

%c表示输出字符数据(char类型)

%md中m指定输出字段的宽度

%x表示以16进制形式输出整数

  如果需要修改字符串,应该用数组

char*中只有它所指的字符数组有结尾的0,才能说它所指的是字符串

字符串输如输出

·scanf不安全,

若要可以在%和s间加数字例如%7s,限制读取的位数

程序参数

·int main(int argc,char const*argv[])

·argv[0]是命令本身

·当使用Unix的符号链接时,反映符号链接的名字

处理字符串需要用

string.h

·strlen<·size_t strlen(const char*s)

·返回s的字符串长度(不包括结尾的0)>

·strcmp<·两个字符串作比较,返回值是两个不相等的字符的差值>

·strcpy< ·char*strcpy(char*restrict dst, const char*restrict stc);

·把src的字符串拷贝到dst

·restrict表明src和dst不重叠(C99)

·返回dst

·为了能链起代码来>

·strcat<char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾>

·strchr<字符串搜索函数(字符串中找字符)

·char*strchr(const char*s,int c);

·char*strrchr(const char*s, int c);

·返回NULL表示没有找到

·strstr

枚举

·枚举是一种用户定义的数据类型,它用关键字enum以如下语法来声明:enum枚举类型名字{名字0,...名字n}

·枚举类型名字通常并不真的使用,要用的是在大括号里的名字,因为他们就是常量符号,它们的类型是int,值则依次从0到n.如:enum colors{red,yellow,green};

枚举比宏好,因为枚举有int类型

结构类型

声明结构的形式

①struct point{

  int x;

  int y;

};

struct point p1,p2;

p1和p2都是point里面有x和y的值

②struct{

   int x;

   int y;

}p1,p2;

p1和p2都是一种无名结构,里面有x和y

③struct point{

  int x;

  int y;

}p1,p2;

p1和p2都是point里面有x和y的值t

对于第一和第三种形式,都声明了结构point.但是第二种形式没有声明point,只是定义了两个变量.

结构成员

·结构和数组有点像

·数组用[]运算符和下标访问其成员

·a[0]=10;

·结构用.运算符和名字访问其成员

·today.day

·student.firstName

·pl.x

·pl.y

结构运算

·要访问整个结构,直接用结构变量的名字

·对于整个结构,可以做赋值\取地址,也可以传递给函数参数

·pl=(struct point){5,10};//相当于pl.x=5;

pl.y=10

·pl=p2;//相当于pl.x=p2.x;pl.y=p2.y;

结构指针

·和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符

·struct date*pDate=&today;

____________________________________________________

结构作为函数参数

int numberOfDays(struct date d)

·整个结构可以作为参数的值传入函数

·这时候是在函数内新建一个结构变量,并复制调用者的结构的值

·也可以返回一个结构

·这与数组完全不同

 

如果有变量定义:

struct rectangle r,*rp;

rp=&r;

那么下面的四种形式是等价的:

r.ptl.x

rp->ptl.x

(r.ptl).x

(rp->ptl).x

但是没有rp->ptl->x

ACLLib  Windows API

·main()成为c语言的入口函数其实和c语言本身无关,你的代码是被一小段叫做启动代码的程序所调用的,它需要一个叫做main的地方

·操作系统把你的可执行程序装载到内存里,启动运行,然后调用你的main函数

产生一个窗口---->窗口结构

在窗口里画东西---->DC

得到用户的鼠标和键盘动作---->消息循环和消息处理代码

____________________________________________________

自定义数据类型(typedef)

·c语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字比如:

typedef int Length;

使得Length成为int类型的别名

·这样,Length这个名字就可以代替int出现在变量定义和参数声明的地方了

Length a,b,len;

Length numbers[10];

____________________________________________________

联合 -union

____________________________________________________

静态本地变量

·在本地变量定义时加上static修饰符就成为静态本地变量

·当函数离开的时候,静态本地变量会继续存在并保持其值

·静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开时的值

·静态本地变量实际上是特殊的全局变量

·它们位于相同的内存区域

·静态本地变量具有全局的生存期,函数内的局部作用域

·static在这里的意思是局部作用域(本地可以访问)

____________________________________________________

*返回指针的函数

·返回本地变量的地址是危险的

·返回全局变量或静态本地变量的地址是安全的

·返回在函数内malloc的内存是安全的,但是容易造成问题

·最好的做法是返回传入的指针

编译预处理指令

·#开头的是编译预处理指令

·它们不是C语言的成分,但是c语言程序离不开它们

·#define用来定义一个宏

·#define<名字><值>

·注意没有结尾的分号,因为不是c的语句

·名字必须是一个单词,值可以是各种东西

·在c语言的编译器开始编译之前,编译预处理程序(cpp)会把程序中的名字换成值

·完全的文本替换

·gcc-save-temps

·如果一个宏的值中有其他的宏的名字,也是会被替换的

·如果一个宏的值超过一行,最后一行之前的行末需要加\

·宏的值后面出现的注释不会被当作宏的值的一部分

预定义的宏

·_LINE_ 源代码行号

·_FILE_ 源代码全路径

·_DATE_ 时间

·_TIME_

·_STDC_

带参数的宏

·#define cube(x)((x)*(x)*(x))

·宏可以带参数

项目

·在Dev C++中新建一个项目,然后把几个源代码文件加入进去

· 对于项目,Dev C++的编译会把一个项目中所有的源代码文件都编译后,链接起来

·有的IDE有分开的编译和构建两个按钮,前者是对单个源代码文件编译,后者是对整个项目做链接

头文件

·把函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中#include这个头文件,就能让编译器在编译的时候知道函数的原型

自己的头文件用””,系统给的用<>.

·#include不是用来引入库的

·stdio.h里只有printf的原型,printf的代码在另外的地方,某个.lib(Windows)或.a(Unix)中

·现在的c语言编译器默认会引入所有的标准库

·#include<stdio.h>只是为了让编译器知道printf函数的原型

保证你调用时给出的参数值是正确的类型

不对外公开的函数

·在函数前加上static就使得它成为只能在所在的编译单元中被使用的函数

·在全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的全局变量

声明

int i;是变量的定义

extern int i;是变量的声明

格式化的输入输出

%[flags][width][.prec][hil]type

scanf:%[flag]type

文本vs二进制

·Unix喜欢用文本文件来做数据存储和程序配置

·交互式终端的出现使得人们喜欢用文本和计算机talk

·Unix的shell提供了一些读写文本的小程序

·Windows喜欢用二级制文件

·DOS是草根文化,并不继承和熟悉Unix文化

·PC刚开始的时候能力有限,DOS的能力更有限,二进制更接近底层

·文本的优势是方便人类读写,而且跨平台

·文本的缺点是程序输入输出要经过格式化,开销大

·二进制的缺点是人类读写困难,而且不跨平台

·int 的大小不一致,大小端的问题.....

·二进制的优点是程序读写快

二级制读写用fread 和fwrite

在文件中定位

·long ftell(FILE*stream);

·int fseek(FILE*stream,long offset, int whence);

·SEEK_SET:从头开始

·SEEK_CUR:从当前位置开始

·SEEK_END:从尾开始(倒过来)

·这样的二进制文件不具有可移植性

·在int为32位的机器上写成的数据文件无法直接在int为64位的机器上正确读出

·解决方案之一是放弃使用int,而是typedef具有明确大小的类型

·更好的方案是用文本

·其实所有的文件最终都是二进制的

·文本文件无非是用最简单的方式可以读写的文件

·more\tail

·cat

·vi

·而二进制文件是需要专门的程序来读写的文件

·文本文件的输入输出是格式化\可能经过转码

按位运算(把整数当二进制进行按位运算)

逻辑运算vs按位运算

·对于逻辑运算,它只看到两个值:0和1

·可以认为逻辑运算相当于把所有非0值都变成1,然后做按位运算

对一个数做两次异或运算则还是原来那个数

左移<<

·i<<j

·i中所有的位向左移动j个位置,而右边填入0

·所有小于int的类型,移位以int的方式来做,结果是int

·x<<1等价于x*=2

·x<<=n等价于x*=

关于结构体类型的定义的总结;

一般格式就是;

struct 结构体名(也就是可选标记名)

{

    成员变量;

信息安全( 1,传统的网络安全2.云安全3公共安全)

什么是信息安全?保护数据

2017年wannacry病毒席卷全球/撞库/暗网:隐匿性.洋葱路由不可追踪/表层网络,深网,暗网/

熟悉web渗透测试方法和功放技术,包括SQL注入.xss跨站.CSRF伪造请求.命令执行等owasp top10安全漏洞与防御,有一定的漏洞分析和挖掘能力;

安全岗位核心技能需求:

熟悉Linux,Windows不同平台的渗透测试,了解常用web框架.数据库,中间件,和操作系统 弱点以及相关攻防技术;

熟悉国内外主流安全工具包括Kali Linux,metasploit,Nessus,nmap.awvs,burp,appscan等

熟悉一门编程语言,有一定的代码编写能力;

Wireshark

c语言

嵌入式阅读 结合关系一般自左向右,单目+-和赋值=自右向左\这样的表达式太复杂,不容易阅读和理解

#include <stdio.h>

在 C 语言中,sizeof () 是一个判断数据类型或者表达式长度的运算符。

整数类型

char:一字节 8比特

short: 2字节

int:取决于编译器CPU,通常的意义是一个字

long:取决于编译器,通常是两个字

longlong

一台计算器的字长是指当前计算器reg(寄存器)的宽度

寄存器一次可以处理的数据=int 一个字

int就是用来表达寄存器的

如何表示负数

二进制负数

一个字节可以表达的数:

00000000-11111111(0-255)

三种方案:

1,仿照十进制,有一个特殊的标志表示负数

  1. 取中间的数为0,如1000000表示0,比它小的是负数,比它大的是正数
  2. 补码

补码:对于-a,其补码就是0-a,实际上是2的n次方-a,n是这种类型的位数

补码的意义就是拿补码和原码可以加出一个溢出的

整数的输入输出

只有两种形式:int或long long

%d:int

%u:unsigned

%ld:long long

%lu:unsigned long long

一个以0开始的数字字面量是8进制

一个以0x开始的数字字面量是16进制

16进制很适合表达二进制数据,因为4位二进制正好是一个16进制位

8进制的一位数字正好表达3位二进制

因为早期计算机的字长是12的倍数,而非8

带小数点的字面量是double而非float

float需要用f或F后缀来表明身份

*浮点数内部表达

浮点数在计算时是由专用的硬件部分实现的

计算double和float所用的部件是一样的

^字符类型

char是一种整数,也是一种特殊的类型:字符.这是因为:

用单引号表示的字符字面量:a

‘’也是一个字符

printf和scanf里用%c来输入输出字符

*逃逸字符

用来表达无法印出来的控制字符或特殊字符,它由一个反斜杠\开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符

不同的shell做出不同的反应

||优先级大于&&

count[x]++;

*取地址运算

sizeof

是一个运算符,给出某个类型或变量在内存中所占据的字节数

运算符&

·scanf(%d,&i);里的&

·获得变量的地址,他的操作数必须是变量

指针

就是保存地址的变量

int*P=&i

变量的值是内存的地址

·普通变量的值是实际的值

·指针变量的值是具有实际值的变量的地址

访问那个地址上的变量*

* 是一个单目运算符,用来访问指针的值所表示的地址上的变量

·可以做右值也可以做左值(可以放等号两边)

·int k=*p;

·*p=k+1

^指针的使用

·交换两个变量的值

 

·函数返回多个值,某些值就只能通过指针返回

·传入的参数实际上是需要保存带回的结果的变量

函数返回运算的状态,结果通过指针返回

常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:

-1或0

但是当任何数值都是有效的可能结果是,就得分开返回了

·后续的语言(c++,java)采用了异常机制来解决这个问题

*指针最常见的错误

·定义了指针变量,还没有指向任何变量,就开始使用指针

传入函数的数组成了什么?

·函数参数表中的数组实际上是指针

·sizeof(a)==sizeof(int*)

·但是可以用数组的运算符[]进行运算

数组变量是特殊的指针

·数组变量本身表达地址所以

·int a[10];int*p=a;//无需用&取地址

·但是数组的单元表达的是变量,需要用&取地址

·a==&a[0]

·[]运算符可以对数组做,也可以对指针做:

·数组变量是const的指针,所以不能被赋值

·int a[]<==>int *const a=.....

C语言const的用法详解,C语言常量定义详解 (biancheng.net)

判断哪个被const了的标志是const在*的前面还是后面

^保护数组值

·因为把数组传入函数时,传递的是地址,所以那个函数内部可以修改数组的值

·为了保护数组不被函数破坏,可以设置参数为const

·int sum (const int a[],int length);

·给一个指针加1表示要让指针指向下一个变量

int a[10];

int*p=a;

*(p+1)-->a[1]

·如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义

*p++

·取出p所指的那个数据来,完事之后顺便把p移到下一个位置去

·*的优先级虽然高,但是没有++高

·常用于数组类的连续空间操作

·在某些CPU上,这可以直接被翻译成一条汇编指令

0地址

·当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址

·所以你的指针不应该具有0值

·因此可以用0地址来表示特殊的事情

·返回的指针是无效的

·指针没有被真正初始化(先初始化为0)

·NULL是一个预定定义的符号,表示0地址

·有的编译器不愿意用0来表示0地址

指针的类型

·无论指向什么类型,所有的指针的大小都是一样的,因为都是地址

·但是指向不同类型的指针是不能直接互相赋值的

·这是为了避免用错指针

指针类型转换

·void*表示不知道指向什么东西的指针

·计算时与char*相同(但不相通)

·指针也可以转换类型

·int*p=&i;void*q=(void*)p;

·这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量

·我不再当你是int,我认为你就是个void!

size_t类型表示c中任何对象所能达到的最大长度,它是无符号整数.

字符串

·以0(整数0)结尾的一串字符

·0或\0是一样的,但是和0不同

·0标志字符串的结束,但它不是字符串的一部分

·计算字符串长度的时候不包含这个0

·字符串以数组的形式存在,以数组或指针的形式访问

·更多的是以指针的形式

·string.h里有很多处理字符串的函数

字符串变量

·char*str=hello;

·char word[]=Hello;

·char line[10]=Hello;

·Hello会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0

·两个相邻的字符串常量会被自动连接起来

·C语言的字符串是以字符数组的形态存在的

·不能用运算符对字符串做运算

·通过数组的方式可以遍历字符串

·唯一特殊的地方是字符串字面量可以用来初始化字符数组

%*c表示跳过这个字符

%作为引导符,控制输入输出的格式.

%s表示输出字符串形式

%f表示输出为浮点型数据

%o表示以8进制形式输出整数

%d表示输出整形数据

%ld表示输出为长整型数据

%u表示输出格式为无符号数据

%c表示输出字符数据(char类型)

%md中m指定输出字段的宽度

%x表示以16进制形式输出整数

  如果需要修改字符串,应该用数组

char*中只有它所指的字符数组有结尾的0,才能说它所指的是字符串

字符串输如输出

·scanf不安全,

若要可以在%和s间加数字例如%7s,限制读取的位数

程序参数

·int main(int argc,char const*argv[])

·argv[0]是命令本身

·当使用Unix的符号链接时,反映符号链接的名字

处理字符串需要用

string.h

·strlen<·size_t strlen(const char*s)

·返回s的字符串长度(不包括结尾的0)>

·strcmp<·两个字符串作比较,返回值是两个不相等的字符的差值>

·strcpy< ·char*strcpy(char*restrict dst, const char*restrict stc);

·把src的字符串拷贝到dst

·restrict表明src和dst不重叠(C99)

·返回dst

·为了能链起代码来>

·strcat<char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾>

·strchr<字符串搜索函数(字符串中找字符)

·char*strchr(const char*s,int c);

·char*strrchr(const char*s, int c);

·返回NULL表示没有找到

·strstr

枚举

·枚举是一种用户定义的数据类型,它用关键字enum以如下语法来声明:enum枚举类型名字{名字0,...名字n}

·枚举类型名字通常并不真的使用,要用的是在大括号里的名字,因为他们就是常量符号,它们的类型是int,值则依次从0到n.如:enum colors{red,yellow,green};

枚举比宏好,因为枚举有int类型

结构类型

声明结构的形式

①struct point{

  int x;

  int y;

};

struct point p1,p2;

p1和p2都是point里面有x和y的值

②struct{

   int x;

   int y;

}p1,p2;

p1和p2都是一种无名结构,里面有x和y

③struct point{

  int x;

  int y;

}p1,p2;

p1和p2都是point里面有x和y的值t

对于第一和第三种形式,都声明了结构point.但是第二种形式没有声明point,只是定义了两个变量.

结构成员

·结构和数组有点像

·数组用[]运算符和下标访问其成员

·a[0]=10;

·结构用.运算符和名字访问其成员

·today.day

·student.firstName

·pl.x

·pl.y

结构运算

·要访问整个结构,直接用结构变量的名字

·对于整个结构,可以做赋值\取地址,也可以传递给函数参数

·pl=(struct point){5,10};//相当于pl.x=5;

pl.y=10

·pl=p2;//相当于pl.x=p2.x;pl.y=p2.y;

结构指针

·和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符

·struct date*pDate=&today;

____________________________________________________

结构作为函数参数

int numberOfDays(struct date d)

·整个结构可以作为参数的值传入函数

·这时候是在函数内新建一个结构变量,并复制调用者的结构的值

·也可以返回一个结构

·这与数组完全不同

 

如果有变量定义:

struct rectangle r,*rp;

rp=&r;

那么下面的四种形式是等价的:

r.ptl.x

rp->ptl.x

(r.ptl).x

(rp->ptl).x

但是没有rp->ptl->x

ACLLib  Windows API

·main()成为c语言的入口函数其实和c语言本身无关,你的代码是被一小段叫做启动代码的程序所调用的,它需要一个叫做main的地方

·操作系统把你的可执行程序装载到内存里,启动运行,然后调用你的main函数

产生一个窗口---->窗口结构

在窗口里画东西---->DC

得到用户的鼠标和键盘动作---->消息循环和消息处理代码

____________________________________________________

自定义数据类型(typedef)

·c语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字比如:

typedef int Length;

使得Length成为int类型的别名

·这样,Length这个名字就可以代替int出现在变量定义和参数声明的地方了

Length a,b,len;

Length numbers[10];

____________________________________________________

联合 -union

____________________________________________________

静态本地变量

·在本地变量定义时加上static修饰符就成为静态本地变量

·当函数离开的时候,静态本地变量会继续存在并保持其值

·静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开时的值

·静态本地变量实际上是特殊的全局变量

·它们位于相同的内存区域

·静态本地变量具有全局的生存期,函数内的局部作用域

·static在这里的意思是局部作用域(本地可以访问)

____________________________________________________

*返回指针的函数

·返回本地变量的地址是危险的

·返回全局变量或静态本地变量的地址是安全的

·返回在函数内malloc的内存是安全的,但是容易造成问题

·最好的做法是返回传入的指针

编译预处理指令

·#开头的是编译预处理指令

·它们不是C语言的成分,但是c语言程序离不开它们

·#define用来定义一个宏

·#define<名字><值>

·注意没有结尾的分号,因为不是c的语句

·名字必须是一个单词,值可以是各种东西

·在c语言的编译器开始编译之前,编译预处理程序(cpp)会把程序中的名字换成值

·完全的文本替换

·gcc-save-temps

·如果一个宏的值中有其他的宏的名字,也是会被替换的

·如果一个宏的值超过一行,最后一行之前的行末需要加\

·宏的值后面出现的注释不会被当作宏的值的一部分

预定义的宏

·_LINE_ 源代码行号

·_FILE_ 源代码全路径

·_DATE_ 时间

·_TIME_

·_STDC_

带参数的宏

·#define cube(x)((x)*(x)*(x))

·宏可以带参数

项目

·在Dev C++中新建一个项目,然后把几个源代码文件加入进去

· 对于项目,Dev C++的编译会把一个项目中所有的源代码文件都编译后,链接起来

·有的IDE有分开的编译和构建两个按钮,前者是对单个源代码文件编译,后者是对整个项目做链接

头文件

·把函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中#include这个头文件,就能让编译器在编译的时候知道函数的原型

自己的头文件用””,系统给的用<>.

·#include不是用来引入库的

·stdio.h里只有printf的原型,printf的代码在另外的地方,某个.lib(Windows)或.a(Unix)中

·现在的c语言编译器默认会引入所有的标准库

·#include<stdio.h>只是为了让编译器知道printf函数的原型

保证你调用时给出的参数值是正确的类型

不对外公开的函数

·在函数前加上static就使得它成为只能在所在的编译单元中被使用的函数

·在全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的全局变量

声明

int i;是变量的定义

extern int i;是变量的声明

格式化的输入输出

%[flags][width][.prec][hil]type

scanf:%[flag]type

文本vs二进制

·Unix喜欢用文本文件来做数据存储和程序配置

·交互式终端的出现使得人们喜欢用文本和计算机talk

·Unix的shell提供了一些读写文本的小程序

·Windows喜欢用二级制文件

·DOS是草根文化,并不继承和熟悉Unix文化

·PC刚开始的时候能力有限,DOS的能力更有限,二进制更接近底层

·文本的优势是方便人类读写,而且跨平台

·文本的缺点是程序输入输出要经过格式化,开销大

·二进制的缺点是人类读写困难,而且不跨平台

·int 的大小不一致,大小端的问题.....

·二进制的优点是程序读写快

二级制读写用fread 和fwrite

在文件中定位

·long ftell(FILE*stream);

·int fseek(FILE*stream,long offset, int whence);

·SEEK_SET:从头开始

·SEEK_CUR:从当前位置开始

·SEEK_END:从尾开始(倒过来)

·这样的二进制文件不具有可移植性

·在int为32位的机器上写成的数据文件无法直接在int为64位的机器上正确读出

·解决方案之一是放弃使用int,而是typedef具有明确大小的类型

·更好的方案是用文本

·其实所有的文件最终都是二进制的

·文本文件无非是用最简单的方式可以读写的文件

·more\tail

·cat

·vi

·而二进制文件是需要专门的程序来读写的文件

·文本文件的输入输出是格式化\可能经过转码

按位运算(把整数当二进制进行按位运算)

逻辑运算vs按位运算

·对于逻辑运算,它只看到两个值:0和1

·可以认为逻辑运算相当于把所有非0值都变成1,然后做按位运算

对一个数做两次异或运算则还是原来那个数

左移<<

·i<<j

·i中所有的位向左移动j个位置,而右边填入0

·所有小于int的类型,移位以int的方式来做,结果是int

·x<<1等价于x*=2

·x<<=n等价于x*=

关于结构体类型的定义的总结;

一般格式就是;

struct 结构体名(也就是可选标记名)

{

    成员变量;

};//使用分号表示定义结束;

可变数组

链表

链表是一种常见的基础数据结构,也是一个功能极为强大的数组,可以在节点中定义多种数据类型,还可以根据需要随意怎天,删除,插入节点.链表都有一个头指针,一般以head来表示,存放的是一个地址,链表中的节点分为两类,头结点和一般节点,头结点没有数据域,

链表中每个节点分为两部分,一部分是数据域,一部分是指针域.它的地址部分放一个null,链表到此结束

信息安全( 1,传统的网络安全2.云安全3公共安全)

什么是信息安全?保护数据

2017年wannacry病毒席卷全球/撞库/暗网:隐匿性.洋葱路由不可追踪/表层网络,深网,暗网/

熟悉web渗透测试方法和功放技术,包括SQL注入.xss跨站.CSRF伪造请求.命令执行等owasp top10安全漏洞与防御,有一定的漏洞分析和挖掘能力;

安全岗位核心技能需求:

熟悉Linux,Windows不同平台的渗透测试,了解常用web框架.数据库,中间件,和操作系统 弱点以及相关攻防技术;

熟悉国内外主流安全工具包括Kali Linux,metasploit,Nessus,nmap.awvs,burp,appscan等

熟悉一门编程语言,有一定的代码编写能力;

Wireshark

c语言

嵌入式阅读 结合关系一般自左向右,单目+-和赋值=自右向左\这样的表达式太复杂,不容易阅读和理解

#include <stdio.h>

在 C 语言中,sizeof () 是一个判断数据类型或者表达式长度的运算符。

整数类型

char:一字节 8比特

short: 2字节

int:取决于编译器CPU,通常的意义是一个字

long:取决于编译器,通常是两个字

longlong

一台计算器的字长是指当前计算器reg(寄存器)的宽度

寄存器一次可以处理的数据=int 一个字

int就是用来表达寄存器的

如何表示负数

二进制负数

一个字节可以表达的数:

00000000-11111111(0-255)

三种方案:

1,仿照十进制,有一个特殊的标志表示负数

  1. 取中间的数为0,如1000000表示0,比它小的是负数,比它大的是正数
  2. 补码

补码:对于-a,其补码就是0-a,实际上是2的n次方-a,n是这种类型的位数

补码的意义就是拿补码和原码可以加出一个溢出的

整数的输入输出

只有两种形式:int或long long

%d:int

%u:unsigned

%ld:long long

%lu:unsigned long long

一个以0开始的数字字面量是8进制

一个以0x开始的数字字面量是16进制

16进制很适合表达二进制数据,因为4位二进制正好是一个16进制位

8进制的一位数字正好表达3位二进制

因为早期计算机的字长是12的倍数,而非8

带小数点的字面量是double而非float

float需要用f或F后缀来表明身份

*浮点数内部表达

浮点数在计算时是由专用的硬件部分实现的

计算double和float所用的部件是一样的

^字符类型

char是一种整数,也是一种特殊的类型:字符.这是因为:

用单引号表示的字符字面量:a

‘’也是一个字符

printf和scanf里用%c来输入输出字符

*逃逸字符

用来表达无法印出来的控制字符或特殊字符,它由一个反斜杠\开头,后面跟上另一个字符,这两个字符合起来,组成了一个字符

不同的shell做出不同的反应

||优先级大于&&

count[x]++;

*取地址运算

sizeof

是一个运算符,给出某个类型或变量在内存中所占据的字节数

运算符&

·scanf(%d,&i);里的&

·获得变量的地址,他的操作数必须是变量

指针

就是保存地址的变量

int*P=&i

变量的值是内存的地址

·普通变量的值是实际的值

·指针变量的值是具有实际值的变量的地址

访问那个地址上的变量*

* 是一个单目运算符,用来访问指针的值所表示的地址上的变量

·可以做右值也可以做左值(可以放等号两边)

·int k=*p;

·*p=k+1

^指针的使用

·交换两个变量的值

 

·函数返回多个值,某些值就只能通过指针返回

·传入的参数实际上是需要保存带回的结果的变量

函数返回运算的状态,结果通过指针返回

常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:

-1或0

但是当任何数值都是有效的可能结果是,就得分开返回了

·后续的语言(c++,java)采用了异常机制来解决这个问题

*指针最常见的错误

·定义了指针变量,还没有指向任何变量,就开始使用指针

传入函数的数组成了什么?

·函数参数表中的数组实际上是指针

·sizeof(a)==sizeof(int*)

·但是可以用数组的运算符[]进行运算

数组变量是特殊的指针

·数组变量本身表达地址所以

·int a[10];int*p=a;//无需用&取地址

·但是数组的单元表达的是变量,需要用&取地址

·a==&a[0]

·[]运算符可以对数组做,也可以对指针做:

·数组变量是const的指针,所以不能被赋值

·int a[]<==>int *const a=.....

C语言const的用法详解,C语言常量定义详解 (biancheng.net)

判断哪个被const了的标志是const在*的前面还是后面

^保护数组值

·因为把数组传入函数时,传递的是地址,所以那个函数内部可以修改数组的值

·为了保护数组不被函数破坏,可以设置参数为const

·int sum (const int a[],int length);

·给一个指针加1表示要让指针指向下一个变量

int a[10];

int*p=a;

*(p+1)-->a[1]

·如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义

*p++

·取出p所指的那个数据来,完事之后顺便把p移到下一个位置去

·*的优先级虽然高,但是没有++高

·常用于数组类的连续空间操作

·在某些CPU上,这可以直接被翻译成一条汇编指令

0地址

·当然你的内存中有0地址,但是0地址通常是个不能随便碰的地址

·所以你的指针不应该具有0值

·因此可以用0地址来表示特殊的事情

·返回的指针是无效的

·指针没有被真正初始化(先初始化为0)

·NULL是一个预定定义的符号,表示0地址

·有的编译器不愿意用0来表示0地址

指针的类型

·无论指向什么类型,所有的指针的大小都是一样的,因为都是地址

·但是指向不同类型的指针是不能直接互相赋值的

·这是为了避免用错指针

指针类型转换

·void*表示不知道指向什么东西的指针

·计算时与char*相同(但不相通)

·指针也可以转换类型

·int*p=&i;void*q=(void*)p;

·这并没有改变p所指的变量的类型,而是让后人用不同的眼光通过p看它所指的变量

·我不再当你是int,我认为你就是个void!

size_t类型表示c中任何对象所能达到的最大长度,它是无符号整数.

字符串

·以0(整数0)结尾的一串字符

·0或\0是一样的,但是和0不同

·0标志字符串的结束,但它不是字符串的一部分

·计算字符串长度的时候不包含这个0

·字符串以数组的形式存在,以数组或指针的形式访问

·更多的是以指针的形式

·string.h里有很多处理字符串的函数

字符串变量

·char*str=hello;

·char word[]=Hello;

·char line[10]=Hello;

·Hello会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0

·两个相邻的字符串常量会被自动连接起来

·C语言的字符串是以字符数组的形态存在的

·不能用运算符对字符串做运算

·通过数组的方式可以遍历字符串

·唯一特殊的地方是字符串字面量可以用来初始化字符数组

%*c表示跳过这个字符

%作为引导符,控制输入输出的格式.

%s表示输出字符串形式

%f表示输出为浮点型数据

%o表示以8进制形式输出整数

%d表示输出整形数据

%ld表示输出为长整型数据

%u表示输出格式为无符号数据

%c表示输出字符数据(char类型)

%md中m指定输出字段的宽度

%x表示以16进制形式输出整数

  如果需要修改字符串,应该用数组

char*中只有它所指的字符数组有结尾的0,才能说它所指的是字符串

字符串输如输出

·scanf不安全,

若要可以在%和s间加数字例如%7s,限制读取的位数

程序参数

·int main(int argc,char const*argv[])

·argv[0]是命令本身

·当使用Unix的符号链接时,反映符号链接的名字

处理字符串需要用

string.h

·strlen<·size_t strlen(const char*s)

·返回s的字符串长度(不包括结尾的0)>

·strcmp<·两个字符串作比较,返回值是两个不相等的字符的差值>

·strcpy< ·char*strcpy(char*restrict dst, const char*restrict stc);

·把src的字符串拷贝到dst

·restrict表明src和dst不重叠(C99)

·返回dst

·为了能链起代码来>

·strcat<char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾>

·strchr<字符串搜索函数(字符串中找字符)

·char*strchr(const char*s,int c);

·char*strrchr(const char*s, int c);

·返回NULL表示没有找到

·strstr

枚举

·枚举是一种用户定义的数据类型,它用关键字enum以如下语法来声明:enum枚举类型名字{名字0,...名字n}

·枚举类型名字通常并不真的使用,要用的是在大括号里的名字,因为他们就是常量符号,它们的类型是int,值则依次从0到n.如:enum colors{red,yellow,green};

枚举比宏好,因为枚举有int类型

结构类型

声明结构的形式

①struct point{

  int x;

  int y;

};

struct point p1,p2;

p1和p2都是point里面有x和y的值

②struct{

   int x;

   int y;

}p1,p2;

p1和p2都是一种无名结构,里面有x和y

③struct point{

  int x;

  int y;

}p1,p2;

p1和p2都是point里面有x和y的值t

对于第一和第三种形式,都声明了结构point.但是第二种形式没有声明point,只是定义了两个变量.

结构成员

·结构和数组有点像

·数组用[]运算符和下标访问其成员

·a[0]=10;

·结构用.运算符和名字访问其成员

·today.day

·student.firstName

·pl.x

·pl.y

结构运算

·要访问整个结构,直接用结构变量的名字

·对于整个结构,可以做赋值\取地址,也可以传递给函数参数

·pl=(struct point){5,10};//相当于pl.x=5;

pl.y=10

·pl=p2;//相当于pl.x=p2.x;pl.y=p2.y;

结构指针

·和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符

·struct date*pDate=&today;

____________________________________________________

结构作为函数参数

int numberOfDays(struct date d)

·整个结构可以作为参数的值传入函数

·这时候是在函数内新建一个结构变量,并复制调用者的结构的值

·也可以返回一个结构

·这与数组完全不同

 

如果有变量定义:

struct rectangle r,*rp;

rp=&r;

那么下面的四种形式是等价的:

r.ptl.x

rp->ptl.x

(r.ptl).x

(rp->ptl).x

但是没有rp->ptl->x

ACLLib  Windows API

·main()成为c语言的入口函数其实和c语言本身无关,你的代码是被一小段叫做启动代码的程序所调用的,它需要一个叫做main的地方

·操作系统把你的可执行程序装载到内存里,启动运行,然后调用你的main函数

产生一个窗口---->窗口结构

在窗口里画东西---->DC

得到用户的鼠标和键盘动作---->消息循环和消息处理代码

____________________________________________________

自定义数据类型(typedef)

·c语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字比如:

typedef int Length;

使得Length成为int类型的别名

·这样,Length这个名字就可以代替int出现在变量定义和参数声明的地方了

Length a,b,len;

Length numbers[10];

____________________________________________________

联合 -union

____________________________________________________

静态本地变量

·在本地变量定义时加上static修饰符就成为静态本地变量

·当函数离开的时候,静态本地变量会继续存在并保持其值

·静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开时的值

·静态本地变量实际上是特殊的全局变量

·它们位于相同的内存区域

·静态本地变量具有全局的生存期,函数内的局部作用域

·static在这里的意思是局部作用域(本地可以访问)

____________________________________________________

*返回指针的函数

·返回本地变量的地址是危险的

·返回全局变量或静态本地变量的地址是安全的

·返回在函数内malloc的内存是安全的,但是容易造成问题

·最好的做法是返回传入的指针

编译预处理指令

·#开头的是编译预处理指令

·它们不是C语言的成分,但是c语言程序离不开它们

·#define用来定义一个宏

·#define<名字><值>

·注意没有结尾的分号,因为不是c的语句

·名字必须是一个单词,值可以是各种东西

·在c语言的编译器开始编译之前,编译预处理程序(cpp)会把程序中的名字换成值

·完全的文本替换

·gcc-save-temps

·如果一个宏的值中有其他的宏的名字,也是会被替换的

·如果一个宏的值超过一行,最后一行之前的行末需要加\

·宏的值后面出现的注释不会被当作宏的值的一部分

预定义的宏

·_LINE_ 源代码行号

·_FILE_ 源代码全路径

·_DATE_ 时间

·_TIME_

·_STDC_

带参数的宏

·#define cube(x)((x)*(x)*(x))

·宏可以带参数

项目

·在Dev C++中新建一个项目,然后把几个源代码文件加入进去

· 对于项目,Dev C++的编译会把一个项目中所有的源代码文件都编译后,链接起来

·有的IDE有分开的编译和构建两个按钮,前者是对单个源代码文件编译,后者是对整个项目做链接

头文件

·把函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中#include这个头文件,就能让编译器在编译的时候知道函数的原型

自己的头文件用””,系统给的用<>.

·#include不是用来引入库的

·stdio.h里只有printf的原型,printf的代码在另外的地方,某个.lib(Windows)或.a(Unix)中

·现在的c语言编译器默认会引入所有的标准库

·#include<stdio.h>只是为了让编译器知道printf函数的原型

保证你调用时给出的参数值是正确的类型

不对外公开的函数

·在函数前加上static就使得它成为只能在所在的编译单元中被使用的函数

·在全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的全局变量

声明

int i;是变量的定义

extern int i;是变量的声明

格式化的输入输出

%[flags][width][.prec][hil]type

scanf:%[flag]type

文本vs二进制

·Unix喜欢用文本文件来做数据存储和程序配置

·交互式终端的出现使得人们喜欢用文本和计算机talk

·Unix的shell提供了一些读写文本的小程序

·Windows喜欢用二级制文件

·DOS是草根文化,并不继承和熟悉Unix文化

·PC刚开始的时候能力有限,DOS的能力更有限,二进制更接近底层

·文本的优势是方便人类读写,而且跨平台

·文本的缺点是程序输入输出要经过格式化,开销大

·二进制的缺点是人类读写困难,而且不跨平台

·int 的大小不一致,大小端的问题.....

·二进制的优点是程序读写快

二级制读写用fread 和fwrite

在文件中定位

·long ftell(FILE*stream);

·int fseek(FILE*stream,long offset, int whence);

·SEEK_SET:从头开始

·SEEK_CUR:从当前位置开始

·SEEK_END:从尾开始(倒过来)

·这样的二进制文件不具有可移植性

·在int为32位的机器上写成的数据文件无法直接在int为64位的机器上正确读出

·解决方案之一是放弃使用int,而是typedef具有明确大小的类型

·更好的方案是用文本

·其实所有的文件最终都是二进制的

·文本文件无非是用最简单的方式可以读写的文件

·more\tail

·cat

·vi

·而二进制文件是需要专门的程序来读写的文件

·文本文件的输入输出是格式化\可能经过转码

按位运算(把整数当二进制进行按位运算)

逻辑运算vs按位运算

·对于逻辑运算,它只看到两个值:0和1

·可以认为逻辑运算相当于把所有非0值都变成1,然后做按位运算

对一个数做两次异或运算则还是原来那个数

左移<<

·i<<j

·i中所有的位向左移动j个位置,而右边填入0

·所有小于int的类型,移位以int的方式来做,结果是int

·x<<1等价于x*=2

·x<<=n等价于x*=

关于结构体类型的定义的总结;

一般格式就是;

struct 结构体名(也就是可选标记名)

{

    成员变量;

};//使用分号表示定义结束;

可变数组

链表

链表是一种常见的基础数据结构,也是一个功能极为强大的数组,可以在节点中定义多种数据类型,还可以根据需要随意怎天,删除,插入节点.链表都有一个头指针,一般以head来表示,存放的是一个地址,链表中的节点分为两类,头结点和一般节点,头结点没有数据域,

链表中每个节点分为两部分,一部分是数据域,一部分是指针域.它的地址部分放一个null,链表到此结束

};//使用分号表示定义结束;

可变数组

链表

链表是一种常见的基础数据结构,也是一个功能极为强大的数组,可以在节点中定义多种数据类型,还可以根据需要随意怎天,删除,插入节点.链表都有一个头指针,一般以head来表示,存放的是一个地址,链表中的节点分为两类,头结点和一般节点,头结点没有数据域,

链表中每个节点分为两部分,一部分是数据域,一部分是指针域.它的地址部分放一个null,链表到此结束

  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值