C语言 操作符、关键字、知识点、函数使用

一、操作符

1、<<、>>移位操作符


int a=2;
int b=a<<1;  //移位操作符<<、>> ,转为二进制数然后移动 
printf("%d\n",b);//b的值为4 

2、 ! 逻辑反操作

//0表示假,非0表示真

int a=0;

printf("%d",!a);//本来a是0,为假,!a为真,值为1

//!把真变假,把假变真

such as


if(a){//如果a为真,进入if语句 
......
}
if(!a){//如果a为假,进入if语句 
......
}

3、sizeof

3.1 介绍

//计算类型或者变量的大小 ,是一个操作符,不是函数

//算出来的结果的类型是unsigned int

int i=-1;

i>sizeof(i)//比较大小,在计算的时候,先把i变成无符号整形,10000……0001,超级大,而sizeof(i)的结果仍然为4


int arr[10]={0};
printf("%d",sizeof(arr));//结果是40,计算的是数组的总大小,单位是字节 
printf("%d",sizeof(arr[0]));//结果是4,表示数组第一个元素的大小
int sz=sizeof(arr)/sizeof(arr[0]);//结果是10,得到数组元素的个数 

3.2 sizeof与strlen例题

sizeof(数组名),计算整个数组的大小

&数组名,数组名表示整个数组,取出的是整个数组的地址

除此之外,所有数组名都是数组首元素的地址

(1)整型数组

int a[]={1,2,3,4};
printf("%d\n",sizeof(a)); // 16
printf("%d\n",sizeof(a+0)); // 4 or 8 ,a+0是第一个元素的地址,计算的是地址的大小,在32位是4,64位是8 
printf("%d\n",sizeof(*a)); // 4 , *a是数组的第一个元素,计算的是第一个元素的大小 
printf("%d\n",sizeof(a+1)); // 4 or 8 , a+1是第二个元素的地址,计算第二个元素的地址的大小 
printf("%d\n",sizeof(a[1])); // 4 ,计算的是第二个元素的大小 

printf("%d\n",sizeof(&a)); // 4 or 8 ,&a是整个数组的地址,但是也是一个地址 ,计算的是一个地址的大小 
printf("%d\n",sizeof(*&a)); // 16 , 取出整个数组的地址,再解引用,得到的是整个数组,计算的是整个数组的大小 
printf("%d\n",sizeof(&a+1));// 4 or 8 ,取出数组的地址再+1,直接跳过该数组,直接到数组后的空间的地址,计算的是数组后的空间的地址的大小 
printf("%d\n",sizeof(&a[0])); // 4 or 8
printf("%d\n",sizeof(&a[0]+1)); // 4 or 8 ,第一个元素的地址+1,计算的是第二个元素的地址 
(2)字符数组
a、char arr[]={};

char arr[]={'a','b','c','d','e','f'};
printf("%d\n",sizeof(arr));// 6
printf("%d\n",sizeof(arr+0));// 4 or 8 ,表示第一个元素的地址,计算的是地址的大小 
printf("%d\n",sizeof(*arr));// 1 ,计算的是第一个元素的大小 
printf("%d\n",sizeof(arr[1]));// 1 ,计算的是第二个元素的大小 
printf("%d\n",sizeof(&arr));// 4 or 8 ,取出的是整个数组的地址,计算的是地址的大小 
printf("%d\n",sizeof(&arr+1));// 4 or 8 ,取出整个数组的地址再+1,直接跳过,计算的是数组后的空间的地址的大小 
printf("%d\n",sizeof(&arr[0]+1));// 4 or 8 ,取出第一个元素的地址+1,计算的是第二个元素的地址的大小 


printf("%d\n",strlen(arr));// 随机值 , strlen遇到\0才停下来,一直找不到,直到遇到\0,所以是随机值 
printf("%d\n",strlen(arr+0));// 随机值,arr和arr+0都是首元素地址 
printf("%d\n",strlen(*arr));// error ,传过去第一个元素是个char,而strlen的参数是char*,会报错 
printf("%d\n",strlen(arr[1]));// error ,传的是第一个元素char类型,参数不匹配,报错 
printf("%d\n",strlen(&arr)); // 随机值 ,传过来整个数组的地址 ,是一个char(*)[6],表示的是一个指针数组,数组里面放的都是地址,满足strlen 的参数要求,于是开始寻找\0,所以是随机值 
printf("%d\n",strlen(&arr+1)); // 随机值-6,直接跳过本数组,和上一个类似 
printf("%d\n",strlen(&arr[0]+1)); // 随机值-1 
b、char arr[]="";

char arr[]="abcdef";//这种方式初始化,最后会有\0 
printf("%d\n",sizeof(arr));//7
printf("%d\n",sizeof(arr+0));//4 or 8
printf("%d\n",sizeof(*arr));// 1
printf("%d\n",sizeof(arr[1]));// 1
printf("%d\n",sizeof(&arr));// 4 or 8
printf("%d\n",sizeof(&arr+1));// 4 or 8
printf("%d\n",sizeof(&arr[0]+1));// 4 or 8


printf("%d\n",strlen(arr));// 6
printf("%d\n",strlen(arr+0));// 6
printf("%d\n",strlen(*arr));// error
printf("%d\n",strlen(arr[1]));// error
printf("%d\n",strlen(&arr));// 6
printf("%d\n",strlen(&arr+1));//随机值 
printf("%d\n",strlen(&arr[0]+1));// 5 
c、char* p="";

char* p="abcdef";
printf("%d\n",sizeof(p));//4 or 8 
printf("%d\n",sizeof(p+1));// 4 or 8
printf("%d\n",sizeof(*p));// 1
printf("%d\n",sizeof(p[0]));// 1
printf("%d\n",sizeof(&p));// 4 or 8
printf("%d\n",sizeof(&p+1));// 4 or 8
printf("%d\n",sizeof(&p[0]+1));//4 or 8


printf("%d\n",strlen(p));//6
printf("%d\n",strlen(p+1));//5 
printf("%d\n",strlen(*p));// error
printf("%d\n",strlen(p[0]));// error
printf("%d\n",strlen(&p));// 随机值 
printf("%d\n",strlen(&p+1));// 随机值 
printf("%d\n",strlen(&p[0]+1));//5

4、++a与a++

++a //前置++,先++后使用

a++ //后置++,先使用后++


int a=10;
int b=++a;//结果为,a=11,b=11 
int b=a++; //结果为,a=10,b=11; 

5、exp1?exp2:exp3; 条件操作符

//条件操作符(三目操作符),若exp1成立,则结果为exp2,若不成立,则结果为exp3


6、逗号表达式

从左往右计算


7、~ 按位取反

//按位取反,将二进制数中,1变0,0变1


8、& 按位与

按(二进制)位与

例如:0000000000010000010001

0010000010001000010001

按位与: 0000000000000000010001,只有两个都为1,才变为1

^ //按位异或

相同为0,相异为1


9、注意事项

(1)关键字不能自己定义,也不能当成变量名使用


二、关键字

1、typedef 类型重定义


typedef unsigned int u_int;//意思是把unsigned int类型简写为u_int类型 

unsigned int num=100;和u_int num=100;意思是一样的


2、static 静态

//静态,修饰局部变量、全局变量、函数

static int a;//保留上一个a的值

全局变量、函数,在其他源文件里也能被使用,具有外部链接属性,

但是被static修饰之后,就变为内部链接属性,只能在自己所在的源文件使用


3、define 定义常量和宏

#define a 100

#define add(x,y) ((x)+(y)) //定义宏


4、break

//在while语句中,用于永久的终止循环


5、continue

//while循环中跳过本次循环continue后面的代码,直接去判断部分,看是否继续进入循环

for循环中,直接跳过continue后面的代码,执行调整语句i++,再进入for循环

在do while语句中,两者结果都一样


6、EOF 文件结束标志

//end of file,其实就是-1,文件结束标志

Ctrl+Z //读取结束,相当于加了个EOF


7、goto

//三层if嵌套,从最内层直接跳到最外层,可以用goto

goto语句只能在一个函数范围内跳转 ,不能跨函数


8、const 常变量

//常变量,不能被修改,但本质上还是变量

修饰指针变量时,

1、如果放在*左边,修饰的是*p,表示指针指向的内容不能通过指针来改变 ,但是指针变量本身可以被修改

//const int* p=&a;

2、如果放在*右边,修饰的是指针变量p,表示指针变量不能被改变,但是指针指向的内容可以被改变

//int* const p=&a;


9、注意事项


三、函数

1、库函数

qsort

(1) 函数内容


void qsort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*));
//库函数qsort有四个参数
//void* base,   base中存放的是待排序数据中第一个对象的地址
//size_t num,   待排序数据中的元素个数
//size_t size,  待排序数据中,每个元素占的字节数
//int (*compar)(const void*, const void*)  函数指针compar,指向用来比较待排序数据中的两个元素的函数
               //第一个const void*,存放第一个元素的地址
   //第二个const void*,存放第二个元素的地址

qsort排序函数,需要引头文件#include <stdlib.h>,并且需要自定义比较函数

(2) 自定义比较函数

a、 整形比较函数

int compar_int(const void* e1, const void* e2)//整形数组排序
{
    return *(int*)e1 - *(int*)e2;//强制类型转换成int
}
b、 字符比较函数

int cmp_char(const void*e1,const void*e2)
{
    return strcmp((char*)e1,(char*)e2);
}
c、 结构体比较函数

int sort_by_age(const void* e1, const void* e2)//结构体数组排序,按年龄排序
{
    return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}


int sort_by_name(const void* e1, const void* e2)//结构体数组排序,按名字排序
{
    return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

perror


perror("自定义信息");

//直接把错误信息打印出来


void perror(const char* str); 

isdigit

是数字则不返回0,不是数字则返回0

使用时需引头文件 #include <ctype.h>


isdigit(arr[i]);

int isdigit ( int c );

isalpha

是字母则不返回0,不是字母则返回0

使用时需要引头文件 #include <ctype.h>


int isalpha(str[i]);

int isalpha ( int c );

isupper

判断是否是大写字母

是大写字母则不返回0,不是大写字母则返回0

需引头文件#include <ctype.h>


int isupper ( int c );

isupper('X');

islower

判断是否是小写字母

是小写字母则不返回0,不是小写字母则返回0

需引头文件#include <ctype.h>


int islower ( int c );

isupper('x');

offsetof

//计算结构体各成员的偏移量

//offsetof函数,需引头文件#include <stddef.h>


#include <stdio.h>
#include <stddef.h>
struct s
{
    char c1;
    int i;
    char c2;
};
int main()
{
    printf("%d\n",offsetof(struct s,c1));
    printf("%d\n",offsetof(struct s,i));
    printf("%d\n",offsetof(struct s,c2));
    return 0;
}

默认对其数为8,结果为0,4,8


2、 字符串函数

gets


gets(str1);

strlen


strlen(str1);

遇到 \0 才停止 ,所以不能用来测char arr[] ={'a','b','c'};的长度


size_t strlen(const char* str);

函数返回值是unsigned int,是无符号数

such as:

strlen("abc")-strlen("abcdef")>0 ,is ture


strcpy


strcpy(str1,str2);

将str2的内容拷贝到str1中


char* strcpy(char* destination,const char* source);

字符串初始化时,str2需要有 \0

str1的空间需要比str2大

str1不能是常量字符串,必须可以被修改

such as: char* str1="xxxxxxxxx";这个str1是常量字符串,不能被修改


strcat


strcat(str1,"想加的字符串");//在str1后面追加字符串

strcat(str1,str2);

在str1后面追加字符串str2


char* strcat(char* destination, const char* source);

str1的空间要能放下追加的字符串

追加的字符串要有\0,而且\0最后会被加在str1上

不能自己追加自己


strcmp


strcmp(str1,str2);

比较str1,str2的大小


int strcmp(const char* str1,const char* str2);

若str1>str2,则返回 >0 的数

若str1==str2,则返回 0

若str<str2,则返回 <0 的数


strncpy


strncpy(str1,str2,len);

把str2的前len个字符,拷贝给str1


char* strncpy(char* destination, const char* source,size_t num);

strnact


strncat(str1,str2,len);//在str1后面追加len长度的str2 

在str1后面追加str2的前len个字符


char* strncat(char* destination,const char* source,size_t num);

strncmp


strncmp(str1,str2,len); 

比较str1和str2的前len个字符的大小


int strncmp(const char* str1,const char* str2,size_t num);

strstr


strstr(str1,str2);
//用来判断str2是否是str1的子串
//如果不是子串,返回空指针NULL
//如果是str1的子串,返回字串的地址(第一次出现的地址)

在使用时加上


char* ret=strstr(str1,str2);
//如果是,则ret==第一次出现的位置 
//如果不是,则ret==0 

char* strstr(char* str1,char* str2);

strtok


strtok(str1,str2);

分割字符串

str2放的是用作分隔符的字符集合


char* strtok(char* str,const char* sep);

sep是个字符串,定义了用作分隔符的字符集合

such as:


char arr[]="abc&rhg@ihj.ihe";
char* p="&@.";
strtok(arr,p);//将arr数组用 & @ . 三个字符隔开 ,将分割字符串直接变为 \0

如果strtok传入的第一个参数不是NULL,则从头开始分割,并且保存分割后更改的\0 的位置

如果此时strtok传入的第一个参数时NULL,则从刚刚保存的位置开始继续分割


strerror


strerror(errno); 

在使用库函数时,如果使用错误,会返回错误码 ,strerror函数的作用是返回错误码所对应的错误信息

需要引用头文件 #include <errno.h>


char* strerror(int ennum);

3、 内存操作函数

memcpy


memcpy(arr1,arr2,num);

将arr2中前num个字节的数据拷贝到arr1中

什么类型都可以拷贝,整形,字符,结构体什么都行


void* memcpy(void* destination,const void* source,size_t num); 

memmove


memmove(arr1,arr2,num);

处理内存重叠的情况

如果arr2的前num个字节的数据拷贝到arr1时,arr1不够大,则需要用memmove函数解决


void* memmove(void* destination,const void* source,size_t num); 

memset


memset(arr,value,num); 

把arr的前num个字节设置成value的值


void* memset(void* ptr,int value,size_t num);

memcmp


memcmp(arr1,arr2,num);

比较前num个字节的数据


int memcmp(const void* ptr1,const void* ptr2,size_t num);

4、动态内存函数

malloc


void* malloc(size_t size);

size指的是开辟的字节数

需引头文件 #include <stdlib.h>或者#include <malloc.h>

使用样例


#include <stdio.h>
#include <stdlib.h>
int  main()
{
    //申请一个包含10个整形的数组 
    int* p=(int *)malloc(10*sizeof(int));
    if(p==NULL)
    {
        perror("main");
        return 0;
     } 
     //使用 
     int i=0;
     for(i=0;i<10;i++)
     {
         scanf("%d",&p[i]);
      } 
      for(i=0;i<10;i++)
      {
          printf("%d ",p[i]);
      }
  
      //回收空间
      free(p);//free不会把p置为空指针,free只能释放动态内存申请的内存
      //void free(void* ptr); 
      p=NULL; //手动置为空指针 
    return 0;
}

calloc


void* calloc(size_t num,size_t size);

需引头文件#include <stdlib.h>

//num是元素个数,size是一个元素所占的字节数

//每一个元素都被初始化为0

使用样例


#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p=(int*)calloc(10,sizeof(int));
    if(p==NULL)
    {
        perror("main");
        return 1;
    }
    int i=0;
    for(i=0;i<10;i++)
    {
        printf("%d\n",*(p+i));
    }
    free(p);
    p=NULL;
    return 0;
 } 

realloc


void*  realloc(void* ptr,size_t size);

需引头文件#include <stdlib.h>

//ptr是要调整的内存地址

//size是调整之后新的大小

使用样例


#include <stdio.h>
#include <stdlib.h>
int main()
{
    int* p=(int*)calloc(10,sizeof(int));
    if(p==NULL)
    {
        perror("main");
        return 1;
    }
    //使用 
    int i=0;
    for(i=0;i<10;i++)
    {
        *(p+i)=5;//全部初始化为5 
     } 
 
     //发现申请的空间小了,需要再增加 10个int
     //用realloc调整
      int* ptr=(int*)realloc(p,20*sizeof(int));//新的大小包括之前申请的大小,即总大小
      //新定义一个临时指针变量ptr,realloc函数在调整过程中,如果出现内存重叠的情况,则自动寻找一块新的空间,将原来的空间销毁。
      //如果,调整的时候,堆区空间不够用,则返回空指针 
      if(ptr!=NULL)
      {
          p=ptr;//不是空指针时,进行赋值 
      }
      //内存释放
      free(p);
      p=NULL;
    return 0;
}

free


free(p);

void free(void* ptr); 

free只能释放动态内存申请的内存

free不会把p置为空指针

p=NULL; //手动置为空指针

动态内存开辟创建常见的错误:

  1. 对NULL指针的解引用

  1. 对动态开辟的空间越界访问

  1. 使用free释放非动态开辟的空间

  1. 使用free释放动态内存中的一部分

  1. 对同一块动态内存多次释放

  1. 动态开辟的空间忘记释放


四、知识点

1、for循环详解


for(int i=1;i<=10;i++)   //平时的循环 
for(int i=0;i<10;i++)    //数组的循环 ,左零右开 
for(;;)     //第一个部分省略,默认i=0,且i的值会保存上一次的,不会再初始为0 
//判断部分省略,恒为真,陷入死循环 

2、do while循环

do

{

循环语句

} while(表达式);

//do while语句至少执行一次,for语句可以一次都不执行


3、字符串数组初始化


char arr[]={'a','b','c'};//求字符串长度strlen时,返回值为随机值 ,这种不会有\0 
char arr[]="abc"; //这种会有个\0 
char* p="abcdefg";

4、二维数组的遍历


int arr[3][4] = { {1,2},{3,4},{4,5} };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
    for (j = 0; j < 4; j++)
    {
        printf("%d ", arr[i][j]);
    }
    printf("\n");
} 

#include <stdio.h>

int main()
{
    char arr[3][6]={0};
    int i=0;
    for(i=0;i<3;i++)
    {
        scanf("%s",arr[i]);//多组字符串的输入
    }
    for(i=0;i<3;i++)
    {
        puts(arr[i]);//多组字符串的输出,puts函数自带\n
    }
}

5、数组名详解

//数组名是数组首元素的地址

//但有两个例外

//1、求sizeof(数组名) ,此时数组名表示整个数组,计算的是整个数组的大小,单位是字节

//2、&数组名 ,此时数组名表示整个数组,取出的是整个数组的地址


  printf("%p\n",&arr);//取出的是整个数组的地址 
  printf("%p\n",arr);//取出的是数组首元素的地址 
  printf("%p\n",arr[0]);//取出的是数组首元素的地址 

6、数据存储

数据在内存中以二进制的形式储存

对于整数来说:

整数的二进制有3种存储方式:原码、反码、补码

正整数:原码、反码、补码三者相同

负整数:(1)先写原码,第一位是符号位,是负数则符号位是1

(2)反码:原码的符号位不变 ,其他位按位取反,1变0,0变1

(3)补码:反码+1

整数在内存中存储的是补码

对于浮点数来说:

根据IEEE 754标准

任意一个二进制浮点数V可以表示成下面形式 :

(-1)^s*M*2^E

(-1)^s表示符号位,当s=0时,V为正数;当s为1是,V为负数。

M表示有效数字,大于等于1,小于2

2^E表示指数位


7、大小端

大端字节序:

把数据的低位字节序的内容存放在高地址处,高位字节序的内容存放在低地址处

小端字节序:

把数据的低位字节序的内容存放在低地址处,高位字节序的内容存放在高地址处

such as:

int a=0x11223344;

//前面是高位字节序,越往后字节序越低

//地址的存放是由低到高,前面低,后面高

如果是11 22 33 44 这样存放,11是高字节序,存放在低地址处,即为大端字节序

如果是44 33 22 11 这样存放,44是低字节序,存放在低地址处,即为小端字节序


8、%u 整型提升

%u,打印无符号整形,进入的是补码,输出的是原码对应的数,需要整形提升,(char输出%u)

char类型,只有一个字节,只能存放8个比特位,即可存放-128~127,如果已经是127,再加1,会变成-128,一个圆圈,轮回

unsigned char的范围是0~255

%d,打印有符号整形


9、数组指针

9.1 一维数组

一般不用


int arr[10]={1,2,3,4,5};
int(*parr)[10]=&arr;//取出的是数组的地址 
for(i=0;i<10;i++)
{
printf("%d ",*((*parr)+i));//指针数组的遍历 ,(*parr)是数组首元素的地址 
 } 

9.2 二维数组


int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
//二维数组的首元素是第一行,即{1,2,3,4,5} 
//遍历的时候
void print(int (*p)[5],int r,int c)
//int (*p)[5],表示一个名为*p的指针,指向一个有5个元素的数组 ,数组中存放的是整形,即二维数组的首地址 
{
    int i=0;
    int j=0;
    for(i=0;i<r;i++)
    {
        for(j=0;j<c;j++)
        {
            printf("%d ",*(*(p+i)+j));
//p存放的是二维数组首元素的地址;即{1,2,3,4,5}的地址 
//(p+i)指的是,二维数组中第一个元素,第二个,第三个……的地址;即{1,2,3,4,5}的地址,{2,3,4,5,6}的地址,{3,4,5,6,7}的地址 
//*(p+i)解引用,指的是二维数组中第一个元素,第二个元素,第三个元素………;即{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} 
//*(p+i)+j指的是二维数组中第i个元素中的第j个元素的地址;即 {1,2,3,4,5}中每个元素的地址 
//*(*(p+i)+j)解引用,指的是二维数组中第i个元素中的第j个元素本身 ;即 {1,2,3,4,5}中的每个元素
        }
    }
} 
 

int* arr[5];//表示一个整型数组 ,数组里面存放的是整形地址
int*(*parr)[5]=&arr;//取出数组的地址
int arr[5];//整形数组 
int  *parr[10];//整形指针数组,存放整形指针的数组 
int (*parr)[10];//数组指针 ,表示一个指针指向一个数组 ,该数组有10个元素,每个元素的类型都是int 
int (*parr[10])[5]; //数组指针数组,parr是一个存放数组指针的数组
//该数组能够存放10个数组指针
//每个数组指针能够指向一个数组,该数组有5个元素,每个元素都是int整形 

10、函数指针

//&加函数名, 或者直接函数名


printf("%p\n",&function);
printf("%p\n",function); 
int (*pf)(int,int)=&function;//定义了一个函数指针变量pf;类型,参数随时变化 

printf("%d\n",(*pf)(3,5));//通过函数指针调用函数 
printf("%d\n",function(3,5));
printf("%d\n",pf(3,5));//这种和(*pf)(3,5)等价,*可以省略 

//pf和函数名是等价的


int (*pfarr[2](int,int))={function1,function2};//函数指针数组pfarr
int (*(*pfarr)[2])(int,int))=&pfarr;//pfarr是一个指向【函数指针数组】的指针,取出的是函数指针数组的地址 

数组名!=&数组名

函数名== &函数名


11、数组传参

11.1 一维数组


void test(int arr[]);
void test(int arr[10]);
void test(int *arr);
void test(int *arr[10]);
void test(int **arr);

11.2 二维数组


void test(int arr[3][5]);
void test(int arr[][5]);
void test(int (*arr)[5]);

12、修改编译器的默认对齐数


#pragma pack(2)

修改默认对齐数,改为2或者其他值

VS编译器的默认对齐数为8


注意事项


五、说明

本博文每日更新,仅为博主学习记录所用,不包含全部操作符、关键字和知识点

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼哥myg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值