C语言基础 9. 指针

C语言基础 9. 指针

9.1. &

  • 运算符&:

    • scanf(“%d”, &i);里的&

    • 获得变量的地址, 它的操作数必须是变量

      • int i;printf(“%x”, &i);
    • 地址的大小是否与int相同取决于编译器和操作系统

      • int i; printf(“%p”, &i);
      • %p: 让printf()输出地址(一个十六进制的数)
  • &不能取的地址:

    • 不能对没有地址的东西取地址
      • printf(“%p”, &(a + b));
      • printf(“%p”, &(a++));
      • printf(“%p”, &(++a)); //error: 表达式必须为左值或函数指示符
  • 试试这些&:

    • 变量的地址

      • printf(“%p\n”, &i);
    • 相邻变量的地址

      • 相邻变量: 指的是定义在相邻位置的变量, 即int i; int p; int b;, 这三个变量是相邻创建的, 也就意味着它们的地址也是相邻的

      • printf(“%p\n”, &i); //000000BE57CFFB14

      • printf(“%p\n”, &p); //000000BE57CFFB34

      • printf(“%p\n”, &b); //000000BE57CFFB54

        • i和p的地址的差值为20byte, p和b的地址的差值为20byte, 按理来说, 它们之间的差值应该是sizeof(i)=4byte, 这是为什么呢?
      • 通过上网查询以及对收集到的信息进行的反复试验, 得出了一些结论

        • 在32位操作系统上:
          • F4-E8=12, 两个相邻变量, Debug模式下, 在int变量的前后各增加了4个字节, 用于存储调试信息, a的后面4个字节, b的前面4个字节, 再加上a本身的4个字节, 刚好是12个字节. 32位上的堆栈内存分配是自上而下, 从大到小, 即F4>E8
        	int a;	//a4 4 4b
        	int b;
        	printf("%p\n", &a);//00D8FDF4
        	printf("%p\n", &b);//00D8FDE8	
        	
        	printf("%d\n", sizeof(a));//4
        	printf("%d\n", sizeof(b));//4
        	printf("%d\n", sizeof(&a));//4
        	printf("%d\n", sizeof(&b));//4
        
        • 在64位操作系统上:
          • 904-8E4=20, 在64位上面, 变量的地址内存变成了8个字节, 同时在编译器的Debug模式下, 存放调式信息的大小也变成了8个字节, a后面8个字节, b前面8个字节, 再加上a本身的4个字节, 刚好是20个字节. 64位的堆栈内存分配是从小到大8E4<904
            在这里插入图片描述
        	int a;	//a8 4 8b
        	int b;
        	printf("%p\n", &a);//0000006CC111F8E4
        	printf("%p\n", &b);//0000006CC111F904	
        	
        	printf("%d\n", sizeof(a));//4
        	printf("%d\n", sizeof(b));//4
        	printf("%d\n", sizeof(&a));//8
        	printf("%d\n", sizeof(&b));//8
        
        • 更改32位或64位, 配置管理器当中的两个选项都要改成64或者32
          在这里插入图片描述

          在这里插入图片描述
          在这里插入图片描述

        • 在64位操作系统上不使用Debug模式, 而是使用Release模式:

          • Debug模式是为了存储调试信息用的, 便于程序员调试错误, 改进代码

          • Release模式是相当于发行版本, 是让用户直接使用的, 所以里面不存放调试信息, 所以两个相邻变量之间的内存相差就等于这两个变量的类型的大小, 也就是sizeof(a)

          • 更改Debug和Release模式
            在这里插入图片描述

    • &的结果的sizeof

      • printf(“%lu\n”, sizeof(&i));
    • 数组的地址
      int arr[10];
      printf(“%p\n”, &arr);
      printf(“%p\n”, arr);
      在这里插入图片描述

    • 数组单元的地址

      • printf(“%p\n”, &arr[0]);
    • 相邻的数组单元的地址
      printf(“%p\n”, &arr[0]);//0000000FF50FF940
      printf(“%p\n”, &arr[1]);//0000000FF50FF944

      • 相差了一个sizeof(int)
      • 通过测试数组的地址得出的结论: &arr = arr = &arr[0]
  • 用于测试的代码:

#include <stdio.h>

int main() {
	//int i = 0; 
	//int p = 0;
	//int b = 1;
	//printf("%p\n", &i);
	//printf("%p\n", &p);
	//printf("%p\n", &b);

	//printf("0x%x\n", &i);
	//printf("%p\n", &i);
	//printf("%lu\n", sizeof(int));
	//printf("%lu\n", sizeof(&i));
	//printf("%lu\n", sizeof(&p));

	///*int a = 1;
	//int b = 2;
	//printf("%p", &(a + b));
	//printf("%p", &(a++));
	//printf("%p", &(++a));*/

	//

	int arr[10];
	printf("%p\n", &arr);//0000000FF50FF940
	printf("%p\n", arr);//0000000FF50FF940
	printf("%p\n", &arr[0]);//0000000FF50FF940
	printf("%p\n", &arr[1]);//0000000FF50FF944
	return 0;
}

9.2. 指针

  • 经典语录:

    • 学计算机一定要有一个非常强大的心理状态, 什么呢? 计算机的所有东西都是人做出来的, 别人能想得出来的, 我也一定能想得出来. 在计算机里头没有任何的黑魔法, 所有的东西只不过是我现在不知道而已, 总有一天我会把所有的细节, 所有的内容的东西全部搞明白了.
  • scanf:

    • scanf()是一个函数, 在它当中有办法拿我们传进去的地址, 把它从标准输入里面分析出来的整数, 放到我们所指定的那个变量里面去

    • 如果能够将取得的变量的地址传递给一个函数, 能否通过这个地址在那个函数内访问这个变量?

      • scanf(“%d”, &i);
    • scanf()的原型应该是怎么样的? 我们需要一个参数能保存别的变量的地址, 如何表达能够保存地址的变量? 如果把它交给一个整数, 有时候整数和地址不见得是相同的类型, 那么什么样的类型可以接收取地址得到的地址呢?

  • 指针:

    • 保存地址的变量
      int i = 1;
      int* p = &i;//p存放了i的地址, 表示p这个指针指向了变量i
      int* p, q;//p表示指针, q表示int
      int *p, q;
  • 指针变量:

    • 普通变量的值是实际的值
    • 指针变量的值是具有实际值的变量的地址
  • 作为参数的指针:

    • void f(int* p);
    • 在被调用的时候得到了某个变量的地址
      • int i = 0;
      • f(&i);
    • 在函数里面可以通过这个指针访问外面的这个i
  • 访问那个地址上的变量*:

    • *: 是一个单目运算符, 用来访问指针的值所表示的地址上的变量
    • *: 可以做右值也可以做左值
      • int k = *p;
      • *p = k + 1;
  • 传入地址:

    • int i;
    • scanf(“%d”, i);
    • 编译没有报错, 但是执行出错了, 为什么?
      • scanf()以为你传进去的是一个地址, 但是你传进去的是一个整数, 然后它用这个整数来做事情, 所以编译不一定出错, 但是运行一定会报错, 因为scanf()把读到的整数写到了不该写的地方
#include <stdio.h>

void f(int* p);
void g(int k);

int main() {
	/*int i = 1;
	int* p = &i;
	int* p, q;
	int *p, q;
	printf("%p\n", p);*/

	int i = 0;
	printf("&i = %p\n", &i);
	f(&i);
	g(i);
	printf("i = %d\n", i);
	return 0;
}

void f(int* p) {
	printf("*p = %d\n", *p);
	*p = 2;
	printf("*p = %d\n", *p);
}

void g(int k) {
	printf("k = %d\n", k);
}

9.3. 指针的使用

  • 指针应用场景一:

    • 交换两个变量的值swap()函数
  • 场景二:

    • 函数返回多个值, 某些值就只能通过指针返回
      • 传入的参数实际上是需要保存带回的结果的变量
    • 找出数组中的最大最小值minmax()函数
  • 场景三:

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

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

      • -1或0(在文件操作会看到大量的例子)
    • 但是当任何数值都是有效的可能结果时, 就得分开返回

      • 后续的语言(C++, Java)采用了异常处理机制来解决这个问题
    • 两个整数做除法divide()函数, 如果除法成功, 返回1, 否则返回0

  • 野指针(指针最常见的错误):

    • 定义了指针变量, 还没有指向任何变量, 就开始使用指针, 这样会导致程序崩溃
      • int* p;
      • *p = 1;
  • swap函数, 交换两个变量的值

#include <stdio.h>

void swap(int* pa, int* pb);

int main() {
	int a = 1;
	int b = 2;
	swap(&a, &b);
	printf("a = %d\n", a);
	printf("b = %d\n", b);
	return 0;
}

void swap(int* pa, int* pb) {
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
  • minmax函数, 找出数组中的最大最小值
#include <stdio.h>

void minmax(int a[], int length, int* min, int* max);

int main(void) {
	int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55, };
	int min, max;
	int length = sizeof(a) / sizeof(a[0]);
	minmax(a, length, &min, &max);
	printf("min = %d, max = %d\n", min, max);
	return 0;
}

void minmax(int a[], int length, int* min, int* max) {
	*min = *max = a[0];
	for (int i = 1; i < length; i++) {
		if (a[i] < *min) {
			*min = a[i];
		}
		else if (a[i] > *max) {
			*max = a[i];
		}
	}
}
  • 两个整数做除法divide()函数, 如果除法成功, 返回1, 否则返回0
#include <stdio.h>

int divide(int a, int b, int* result);

int main(void) {
	int a = 5;
	int b = 2;
	int c;
	if (divide(a, b, &c) == 1) {
		printf("%d / %d = %d\n", a, b, c);
	}
	return 0;
}

int divide(int a, int b, int* result) {
	int ret = 1;
	if (a == 0) ret = 0;
	else {
		*result = a / b;
	}
	return ret;
}
  • 野指针
#include <stdio.h>

int main(void) {
	int k;
	int* p;
	k = 0;
	*p = 1;
	return 0;
}

9.4. 指针与数组

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

    • 函数参数表中的数组实际上是指针
      • sizeof(a) == sizeof(int*)
      • 但是可以用数组的运算符[]进行运算
  • 数组参数:

    • 以下四种参数原型是等价的:
      • int sum(int* arr, int n);
        int sum(int* , int );
        int sum(int arr[], int n);
        int sum(int [], int );
  • 数组变量是特殊的指针:

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

      • int a[10];
        int* p = a; //无需用&取地址
        但是数组的单元表达的是变量, 需要用&取地址
        &a[0], &a[1]
        a == &a[0]
    • []运算符可以对数组做, 也可以对指针做
      p[0] <==> a[0]

    • *运算符可以对指针做, 也可以对数组做
      *a = 25;

    • 数组变量是const的指针, 所以不能被赋值
      int a[] <==> int* const a =…

  • 用于测试的代码:

#include <stdio.h>

void minmax(int a[], int length, int* min, int* max);

int main(void) {
	int a[] = { 1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55, };
	int min, max;
	printf("main sizeof(a) = %lu\n", sizeof(a));
	printf("main a = %p\n", a);
	int length = sizeof(a) / sizeof(a[0]);
	minmax(a, length, &min, &max);
	printf("min = %d, max = %d\n", min, max);
	printf("a[0] = %d\n", a[0]);
	return 0;
}

void minmax(int a[], int length, int* min, int* max) {
	printf("minmax sizeof(a) = %lu\n", sizeof(a));
	printf("minmax a = %p\n", a);
	a[0] = 1000;
	*min = *max = a[0];
	for (int i = 1; i < length; i++) {
		if (a[i] < *min) {
			*min = a[i];
		}
		else if (a[i] > *max) {
			*max = a[i];
		}
	}
}

9.5. 指针与const

  • 指针与const:

    • 指针可以是const, 它所指的那个变量也可以是const
  • 如果指针是const:

    • 表示一旦得到了某个变量的地址, 不能再指向其他变量
      • int* const q = &i;//q是const
        *q = 26;
        q++; //error
  • 如果它所指的变量是const:

    • 表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)
      • int i, j;
        const int* p = &i;
        *p = 26;//error //*p是const
        i = 26;
        p = &j;
  • 这是啥意思?

    • const int* p
      int const* p //上面两个是一样的
      int* const p

    • 判断哪个被const了的标志是const在的前面还是后面, 如果const在前面则*p是const, 如果是在后面则p是const

  • 转换:

    • 总是可以把一个非const的值转换成const的

        void f(const int* x);
        int a = 15;
        f(&a);
        const int b = a;
      
        f(&b);
        b = a + 1; //error
      
    • 当要传递的参数的类型比地址大的时候, 这是常用的手段, 这样既能用比较少的字节数传递值给参数, 又能避免函数对外面的变量的修改

  • const数组:

    • const int a[] = { 1,2,3,4,5,6 };
    • 数组变量已经是const的指针了, 这里的const表明数组的每个单元都是const int
    • 所以必须通过初始化进行赋值
  • 保护数组值:

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

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

      • int sum(const int a[], int length);
#include <stdio.h>

int main() {
	//int i = 1;
	//int* const q = &i;//q是const
	//printf("*q = %d\n", *q);
	// q++
	//*q = 26;
	//printf("*q = %d\n", *q);

	//int i, j;
	//const int* p = &i;
	*p = 26;//error //*p是const
	//i = 26;
	//p = &j;

	void f(const int* x);
	int a = 15;
	f(&a);
	const int b = a;

	f(&b);
	//b = a + 1; //error
	return 0;
}

9.6. 指针运算

  • 指针 + 1:

    • 是在地址值上面+sizeof(指针所指的变量的类型), 而不是直接+1

    • 表示要让指针指向下一个变量

      • int a[10];
        int* p = a;

      • *p -> a[0]
        *(p + 1) == a[1];
        通项公式: *(p + n) == a[n];

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

  • 指针计算:

    • 给指针加减一个整数(+, +=, -, -=)
    • 递增递减(++, --)
    • 两个指针相减
      • 两个地址的差除以sizeof(指针所指变量的类型), 而不是两个地址的差
    • 不能做乘除, 没意义
  • *p++:

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

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

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

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

    • 可以实现一种新的遍历数组的方法:

      	char ac[] = { 0,1,2,3,4,5,6,7,8,9,-1 };
      	char* p = ac;
      	while (*p != -1) {
      		printf("%d\n", *p++);
      	}
      
      • -1表示的是数组结尾的标志, 并不会输出
  • 指针比较:

    • <, <=, ==, >, >=, !=都可以对指针做
    • 比较它们在内存中的地址
    • 数组中的单元的地址肯定是线性递增的
  • 0地址:

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

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

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

      • 返回的指针是无效的
      • 指针没有被真正初始化(先初始化为0)
    • NULL是一个预定定义的符号, 表示0地址

      • 有的编译器不愿意你用0来表示0地址
  • 指针的类型:

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

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

      • 这是为了避免用错指针
      • q = p;
      • warning C4133: “=”: 从“char *”到“int *”的类型不兼容
  • 指针的类型转换:

    • void* 表示不知道指向什么东西的指针
      • 计算时与char*相同(但不相通)
    • 指针也可以转换类型
      • int* p = &i;
      • void* q = (void*)p;
    • 这并没有改变p所指的变量的类型, 而是让后人用不同的眼光通过p看它所指的变量
      • 我不再当你是int啦, 我认为你就是个void
  • 用指针来做什么:

    • 需要传入较大的数据时用作参数
    • 传入数组后对数组做操作
    • 函数返回不止一个结果
      • 需要用函数来修改不止一个变量
    • 动态申请的内存…
//#include <stdio.h>
//
//int main() {
//	char ac[] = { 0,1,2,3,4,5,6,7,8,9, };
//	char* p = ac;
//	printf("p = %p\n", p);//p = 00000054CA5BFBF4
//	printf("p + 1 = %p\n", p + 1);//p + 1 = 00000054CA5BFBF5
//	printf("*(p + 1) = %d\n", *(p + 1));
//	printf("ac[1] = %d\n", ac[1]);
//
//	char* p1 = &ac[5];
//	printf("p1 - p = %p\n", p1 - p);
//
//	int ai[] = { 0,1,2,3,4,5,6,7,8,9, };
//	int* q = ai;
//	printf("q = %p\n", q);//q = 000000EDD69DF5B4
//	printf("q + 1 = %p\n", q + 1);//q + 1 = 000000EDD69DF5B8
//	printf("*(q + 1) = %d\n", *(q + 1));
//	printf("ai[1] = %d\n", ai[1]);
//	/*printf("q - 1 = %p\n", q - 1);*/
//	//q += 1;
//	printf("q = %p\n", q);
//	//printf("++q = %p\n", ++q);
//
//	
//	
//	int* q1 = &ai[6];
//	printf("q1 = %p\n", q1);
//	printf("q1 - q = %p\n", q1 - q);
//
//
//	
//	printf("*q++ = %d\n", *q++);
//	printf("*q = %d\n", *q);
//	return 0;
//}

#include <stdio.h>

int main(void) {
	/*char ac[] = { 0,1,2,3,4,5,6,7,8,9,-1 };
	char* p = ac;
	while (*p != -1) {
		printf("%d\n", *p++);
	}
	int i[] = {1,2,3,4,};
	int* q = i;
	q = p;*/

	int i;
	int* p = &i;
	void* q = (void*)p;
	return 0;
}

9.7. 动态内存分配

  • 输入数据:

    • 如果输入数据时, 县高树你个数, 然后再输入, 要记录每个数据

    • C99可以用变量做数组定义的大小, C99之前呢?

      • 必须使用动态内存分配

      • int* a = (int*)malloc(n * sizeof(int));//借过来

      • free(a);//还回去

  • malloc:

    • #include <stdlib.h>

    • void* malloc(size_t size);

    • 向malloc申请的空间的大小是以字节为单位的

    • 返回的结果时void*, 需要类型转换为自己需要的类型

      • (int*)malloc(n * sizeof(int))
  • 没空间了?

    • 如果申请失败则返回0, 或者叫做NULL
    • 你的系统能给你多大的空间?
      • 分配了35600MB的空间
  • free():

    • 把申请得来的空间还给系统
    • 申请过的空间, 最终都应该还回去
      • 混出来的, 迟早是要还的
  • 常见问题:

    • 申请了没free->长时间运行内存逐渐下降
      • 新手: 忘了
      • 老手: 找不到合适的free的时机
    • free过了再free
    • 地址变过了, 直接去free
  • 经典

    • 纸上得来终觉浅, 绝知此事要躬行
#include <stdio.h>
#include <stdlib.h>

int main() {
	//int n;
	scanf("%d", &n);
	//int arr[10];
	///*for (int i = 0; i < n; i++) {
	//	arr[i] = i;
	//	printf("%d ", arr[i]);
	//}*/
	//int number;
	//int* a;
	//int i;
	//printf("请输入数量: ");
	//scanf("%d", &number);
	//a = (int*)malloc(number * sizeof(int));//借过来

	//for (i = 0; i < number; i++) {
	//	scanf("%d", &a[i]);
	//}

	//for (i = 0; i < number; i++) {
	//	printf("%d ", a[i]);
	//}

	//free(a);//还回去

	
	
	//系统能给你多大的空间
	void* p;
	int count = 0;
	while (p = malloc(100 * 1024 * 1024)) {
		count++;
	}
	printf("分配了%d00MB的空间\n", count);
	return 0;
}
  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "C语言指针详解.pdf" 是一份详细介绍C语言指针概念和使用的PDF文档。C语言中,指针是一种特殊的变量类型,用于存储其他变量的内存地址。 该PDF文档首先详细介绍了指针的定义和声明。指针的声明需要指定指针变量的类型和名称,并使用星号(*)来表示该变量是一个指针指针变量名的前面加上一个星号,可以获取所指向的变量的值,这被称为"解引用"。 文档还介绍了指针的运算。指针可以进行自增和自减运算,指针之间可以进行相减操作,返回的结果表示它们之间的距离或者偏移量。此外,还可以将指针赋值给另一个指针,或者将指针赋值给一个变量,反之亦然。 除了基本的指针概念,文档还详细介绍了指针的常见应用场景。这包括指针作为函数参数,用于在函数内部对传入的变量进行修改。还有通过指针来实现动态内存分配和释放,以及使用指针实现数据结构(如链表和树)等。 此外,该文档还包含一些常见的指针错误和问题的解决方案。这些错误包括空指针引用、野指针引用以及内存泄漏等。文档指出了这些错误的影响以及如何避免它们。 总的来说,"C语言指针详解.pdf" 是一份详细介绍C语言指针概念、使用和常见问题解决方案的文档,对于学习和理解C语言指针的人们是一份宝贵的资料。 ### 回答2: 《C语言指针详解.pdf》是一本关于C语言指针的详细解析的电子书。在这本书中,作者详细介绍了C语言指针的概念、用途和基本语法。 首先,指针C语言中非常重要的概念,它是一种数据类型,用于存储和操作内存地址。指针可以指向各种数据类型,如整数、字符、数组和结构体等。 在《C语言指针详解.pdf》中,作者详细讲解了指针的声明和初始化,以及如何通过指针来访问和修改变量的值。作者还介绍了指针与数组的关系,以及指针和函数之间的关联。 此外,书中还涵盖了指针的高级应用,如指针的算术运算、指向指针指针指针数组等。作者通过丰富的例子和代码来帮助读者理解这些概念和技巧。 《C语言指针详解.pdf》不仅适合C语言初学者,也适合有一定编程基础的读者。通过阅读此书,读者将能够更深入地理解C语言指针的功能和用法,掌握指针在编程中的灵活运用。 总之,《C语言指针详解.pdf》是一本内容详尽且易于理解的C语言指针教程。读者通过阅读此书,可以提高自己在C语言编程中的指针应用能力,从而更好地实现程序的设计和开发。 ### 回答3: 《C语言指针详解.pdf》是一本介绍C语言指针概念和使用方法的详细手册。C语言中的指针是一种非常重要和特殊的数据类型,它提供了直接访问内存地址的能力,使得C语言具有了更高的灵活性和效率。 这本手册首先会介绍指针的基本概念,包括指针变量的定义和声明、指针的初始化和赋值。它会详细讲解指针和变量之间的关系,以及指针的运算规则和使用方法。读者可以学习到如何通过指针操作变量的值和地址,以及如何利用指针实现函数的参数传递和返回值。 接下来,手册会介绍指针和数组之间的关系。C语言中,数组名本质上是一个指向数组首元素的常量指针,因此可以通过指针来操作数组。手册将详细讲解指针和数组的指针算术运算,以及指针和多维数组的关系。 此外,手册还会介绍指针和字符串之间的关系。C语言中,字符串本质上是以空字符结尾的字符数组,可以通过指针来操作字符串。手册将详细讲解指针和字符串的操作,包括字符串的输入输出、字符串的比较和拷贝。 最后,手册还会介绍指针和结构体之间的关系。C语言中,结构体是用户自定义的复合数据类型,可以通过指针来操作结构体。手册将详细讲解指针和结构体的操作,包括结构体指针的定义和使用,以及结构体指针作为函数参数的传递方式。 总之,《C语言指针详解.pdf》是一本深入浅出的指针教程,对于想更深入理解C语言指针的读者来说,是一本非常实用的参考书。无论是初学者还是有一定基础的读者,都可以从中获得很多宝贵的知识和技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值