程序设计入门——C语言翁恺(8)指针与字符串

一、指针

视频1:取地址运算:&运算符取得变量的地址

sizeof()

//sizeof
#include<stdio.h>
int main()
{
	int a;
	a=6;
	printf("sizeof(int)=%ld\n",sizeof(int));      //sizeof(double)
	printf("sizeof(a)=%ld\n",sizeof(a));          //sizeof(a)     
	printf("sizeof(double)=%ld\n",sizeof(double));//sizeof(int)
	return 0;
} 

运算符&

  • scanf("%d",&i);里的&
  • 获得变量的地址,他的操作数必须是变量
  • int i;printf("%x",&i);
int main(void)
{
	int i = 0;
	printf("0x%x\n", &i);    //用%x表示十六进制

	return 0;
 } 

运行结果,需要注意的是,取地址变量在每台PC和每个编译器的结果都是不一样的,我们不必太过关注每次结果不同

    0x62feac

老师视频这里解释他编译器这里有报错,上面的%x需要替换成%p,我用的Dev C++没有报错,这里不再继续探究,该地方跳过,如果报错,记的选择32位编译
 

#include <stdio.h> 

int main(void)
{
	int i = 0;
	int p;
	p = (int)&i; 	//需要(int)&强制转换
	printf("0x%x\n", &p);
	printf("%p\n", &i); 
	return 0;
 } 


强制转换后的运行结果

    0xbfff5d6c
    0xbfff5d6c

上面在编译器里用32位架构编译的结果,老师换成64位再编译,因为强制转换,没有报错。

 在64位架构下用sizeof()求int 与&i 大小,分别为4字节和8字节

 在32位架构下用sizeof()求int 与&i 大小,分别为4字节和4字节

从这里可以看出&可以给我们取出一个变量的地址,从而可以得出,我们需要printf输出一个地址时,需要的是%p,地址和整数是不同的

地址的大小是否与int相同取决于编译器

int i; printf("%p",&i);
 

&不能取的地址

· &不能对没有地址的东西去地址
· 如&(a+b)
· 如&(a++)
· 如&(++a)

#include <stdio.h> 

int main(void)
{
	int i = 0;
	int p;
	p = (int)&i; 
//	p = (int)&(i+p); 
//	p = (int)&(i++); 
//	p = (int)&(++i); 
	printf("0x%x\n", &p);
	printf("%p\n", &i); 
	return 0;
 } 

把上面三个注释分别去掉,得出的报错信息,三个报错类型基本一致的,都是提示不能取这样的值

D:\C\指针.cpp:8:16: error: lvalue required as unary ‘&’ operand p =
(int)&(i+p);

在取地址符的右边必须有一个明确的变量才能取他的地址。

其他类型的&

· 变量的地址
· 相邻的变量的地址
· &的结果的sizeof
· 数组的地址
· 数组单元的地址
· 相邻的数组单元的地址

// 变量的地址
#include <stdio.h> 

int main(void)
{
	int i = 0;
	int p;
	
	printf("%p\n",&i); //  变量的地址
	printf("%p\n", &p);  // 相邻变量的地址
	printf("%p\n",sizeof(int)); // sizeof(int)地址
	return 0;
 } 

执行结果

0061FEAC
0061FEA8
00000004

C在16进制代表的是12,从这里可以看出AC和A8中间差了4位,从上面得知int占据的是4个字节,因此他们是相邻的内存地址,在堆栈里自顶向下分配的,他们的差距是4,刚好等于sizeof(int)

// 数组的地址
    #include <stdio.h> 

int main(void)
{
	int a[10];

	printf("&a=%p\n",&a); // a交给取地址符 
	printf("a=%p\n", a); // a直接当一个地址 
	printf("a[0]=%p\n",&a[0]); // 获取a[0]的地址 
	printf("a[1]=%p\n",&a[1]); // 获取a[1]的地址
	
	return 0;
 } 

执行结果,从这里可以看出相邻单元的数组差距,永远是4

&a =0061FE88
a =0061FE88
a[0] =0061FE88
a[1] =0061FE8C

视频2:指针_指针变量就是记录地址的变量

scanf函数

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

  • scanf("%d", &i)

  • scanf()的原型应该是怎样的?我们需要一个参数能保存别的变量的地址,如何表达能够保存地址的变量?

    scanf()是C语言中的一个输入函数。与printf函数一样,都被声明在头文件stdio.h里,因此在使用scanf函数时要加上#include <stdio.h>。(在有一些实现中,printf函数与scanf函数在使用时可以不使用预编译命令#include <stdio.h>。)它是格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。

什么样的类型,可以接收取地址得到的地址?

指针
· 指针类型的变量就是保存地址的变量

int i;
int* p = &i; //“*”,指针符号,*p,表示p是一个指针
int* p,q;   //q只是一个普通的int类型变量
int *p,q;  //无论*号靠近int还是有空格,意义一样,都表示p是一个指针,指向int

指针变量
· 变量的值是内存的地址
· 普通变量的值是实际的值
· 指针变量的值是具有实际值的变量地址

作为参数的指针

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

void f(int *p); f函数是它是一个int类型的指针,在我们去调用这个f时,就需要给它一个地址,而不能给一个变量本身或者是这个变量的值
int i=0;f(&i); 用&符号取得变量i的地址,将这个地址赋予指针p

#include<stdio.h>

void f(int *p);

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i);// 打印出i的地址
	f(&i);// 将i的地址赋予f 
	return 0;
} 

void f(int *p)
{
	printf(" p=%p\n", p); // 打印出p的值,看他们是否相等	
}

运行结果相同。

这里看出,在main里有一个变量i=6,它的地址是 9C ,我们将9C这个地址取出来赋予了另外一个变量p,p的值是70,同时可以理解为p是一个指针,指向了变量i

有了上面的情况后,在f函数里面,我们有外面的main里面的i的地址,我们不知道它是i,我么只知道它的地址

如果不传地址进去,只得到它的值会是什么情况,看看下面的例子,新增g 函数
 

#include<stdio.h>
void f(int *p);
void g(int k); // 新增g函数 

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i); // 打印出i的地址
	f(&i); // 将i的地址赋予f 
	g(i); // 将i的值赋予g函数 
	return 0;
} 

void f(int *p) // 将*p的值赋予f 
{
	printf(" p=%p\n", p); // 打印出p的值,看他们是否相等	
}

void g(int k) // 
{
	printf(" k=%d\n", k); //打印出g,g得到的是i的值, 
} 

在g函数里,k取到的值k=i=6,k和外面的i没有任何关系,这是之前函数课程里的内容,现在我们通过指针变量p得到了i的地址,这使得f函数里面拥有能够访问外面那个函数的地址的能力

访问那个地址上的变量*

  • *是一个单目运算符,用来访问指针的值所表示的地址上的变量
  • 可以做右值也可以做左值
  • int k = *p;
  • *p = k + 1;
#include<stdio.h>
void f(int *p);
void g(int k); // 新增g函数 

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i); // 打印出i的地址
	f(&i); // 将i的地址赋予f 
	g(i); // 将i的值赋予g函数 
	return 0;
} 

void f(int *p) // 将*p的值赋予f 
{
	printf(" p=%p\n", p); // 打印出p的值,看他们是否相等
	printf("*p=%d\n",*p); // 打印*p的值,将*p看成一个整数的整体
	*p = 26;	
}

void g(int k) // 
{
	printf(" k=%d\n", k); //打印出g,g得到的是i的值
 
} 

输出结果

&i=0061FE9C
p=0061FE9C
*p=6
k=26

 从这里看出,i的值被f函数调用后被改变了
我们在*p=26;时,也可以理解为是对i进行了改变,这就是指针

**指针*左值之所以叫左值
· 是因为出现在赋值号左边的不是变量,而是值,是表达式计算的结果:
· a[0] = 2;// 数组,取下标运算符,a[0]是运算结果
· *p = 3; // 是运算符,p是取得p的指针的地址所代表的变量,表达是运算的结果
· 指针是特殊的值,所以叫做左值

*指针的运算符&
· 互相反作用
· *&yptr -> *(&yptr) -> *(yptr的地址) ->得到地址上的变量 -> yptr
· &yptr -> &(yptr) -> &(y) ->得到y得地址,也就是yptr -> yptr

传入地址
· 为什么
· int i;scanf("%d",i);
· 当我们用scanf时,忘记&时编译没有报错,运行起来就会犯错(因为scanf把读进来的数字写到了不该写的地方)

视频3:指针与数组:为什么数组传进函数后sizeof不对了

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

· 当我们向一段函数传入数组变量,参数接收到的是值,如果我们传入指针时,参数接收到的是也是值(一个地址);
· 如果传入函数的是一个普通变量,它接收到的是一个值
· 如果传入函数的是一个指针,它接收到的也是一个值(地址)
· 如果传入的是一个数组,它接收到的是什么?

#include <stdio.h> 

void minmax(int a[], int len, 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; 
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("min=%d,max=%d\n",min,max);
	
	return 0;
}
void minmax(int a[], int len, int *min, int *max)
{
	int i;
	*min = *max =a[0]; 
	for (i=1;i<len;i++){ 
		if(a[i]<*min){ 
			*min =a[i]; 
		}
		if(a[i]>*max){
			*max =a[i]; 
		}
	}
}

分别在main函数和minmax函数里打印出sizeof(a)的大小

#include <stdio.h> 
/*
取出一组数组里的最小的和最大的值 
*/ 
void minmax(int a[], int len, 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;
	/*[Error] cannot convert 'const char*' to 'int*' for argument '1' to 'void minmax(int*, int, int*, int*)'*/ 
	minmax("main sizeof(a)=%lu\n",sizeof(a)); // main调用之前再看下minmax的大小 
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("min=%d,max=%d\n",min,max);
	
	return 0;
}
void minmax(int a[], int len, int *min, int *max)
{
	int i;
	printf("minmax sizeof(a)=%lu\n",sizeof(a)); //输入minmax的大小 
	*min = *max =a[0]; 
	for (i=1;i<len;i++){ 
		if(a[i]<*min){ 
			*min =a[i]; 
		}
		if(a[i]>*max){
			*max =a[i]; 
		}
	}
}

main函数里,

    sizeof(a)=68

minmax函数里,

    sizeof(a)=4

注意:我的编译器这里会报错,而老师的只是一个警告([Error] cannot convert 'const char’ to ‘int*’ for argument ‘1’ to ‘void minmax(int*, int, int*, int*)’)*
无法将参数’1’的’const char’转换为’int*‘传入’void minmax(int*, int, int*, int*)’*

看到警告或者报错后,我们再试一段代码
 

#include <stdio.h> 
/*
取出一组数组里的最小的和最大的值 
*/ 
void minmax(int a[], int len, 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   a=%p\n",a);
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("min=%d,max=%d\n",min,max);
	
	return 0;
}
void minmax(int a[], int len, int *min, int *max)
{
	int i;
	printf("minmax a=%p\n",a); 
	*min = *max =a[0]; 
	for (i=1;i<len;i++){ 
		if(a[i]<*min){ 
			*min =a[i]; 
		}
		if(a[i]>*max){
			*max =a[i]; 
		}
	}
}

行结果

    main a=0062FE44
    minmax a=0062FE44

将查看a的大小语句改为查看a的指针地址,两个值获取是一样的
问题来了
从这里可以看出maina[]其实就是minmax里的a[]

在这里我们再将minmax函数里的a[0]=1000来看看结果,再回到main里时,它会发生怎样的改变
 

#include <stdio.h> 
#include <stdio.h> 
/*
取出一组数组里的最小的和最大的值 
*/ 
void minmax(int a[], int len, 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   a=%p\n",a);
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("a[0]=%d\n",a[0]); //执行main后我们查看a[0]等于多少 
	printf("min=%d,max=%d\n",min,max);
	
	return 0;
}
void minmax(int a[], int len, int *min, int *max)
{
	int i;
	printf("minmax a=%p\n",a); 
	a[0]=1000;
	*min = *max =a[0]; 
	for (i=1;i<len;i++){ 
		if(a[i]<*min){ 
			*min =a[i]; 
		}
		if(a[i]>*max){
			*max =a[i]; 
		}
	}
}

    main a=0062FE44
    minmax a=0062FE44
    a[0]=1000
    min=2,max=1000

从这里可以看出来a[]它就是一个指针
刚才报错 main函数里获取sizeof(a)的个数,原因是因为a[]它是一个指针
现在我们将两个函数的a[]全部改为*a, 看看编译是否会通过
结果:编译通过,运行正确。

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

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

数组参数

· 以下四种函数原型是等价的:
· int sum(int *ar,int n);
· int sum(int *,int);
· int sum(int ar[], int n);
· int sum(int[], int);


数组变量是特殊的指针

**· 数据变量本身表达地址,所以
· int a[10];int *p =a; //无需用 &取地址
· 但是数组的单元表达的是单个变量,对单个需要用&取地址
· a == &a[0]
· []运算符可以对数组做,也可以对指针做:
· p[0]=*p
· 运算符可以对指针做,也可以对数组做:
·a = 25
· 数组变量是 const的指针,所以不能被赋值,两个数组之前不能互相赋值
· int[a] <==> int * const a=…
 

#include <stdio.h> 
/*
取出一组数组里的最小的和最大的值 
*/ 
void minmax(int *a, int len, 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   a=%p\n",a);
	minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
	printf("a[0]=%d\n",a[0]); //执行main后我们查看a[0]等于多少 
	printf("min=%d,max=%d\n",min,max);
	/* 验证p[0]=*p */
	int *p= &min; 
	printf("  *p=%d\n", *p);
	printf("p[0]=%d\n", p[0]);
	/* 验证*a=a[0]*/
	printf("*a=%d\n",*a); 
 
	return 0;
}
void minmax(int *a, int len, int *min, int *max)
{
	int i;
	
	printf("minmax a=%p\n",a); 
	a[0]= 1000;
	*min = *max =a[0]; 
	for (i=1;i<len;i++){ 
		if(a[i]<*min){ 
			*min =a[i]; 
		}
		if(a[i]>*max){
			*max =a[i]; 
		}
	}
}

执行结果

main a=0062FE40
minmax a=0062FE40
a[0]=1
min=1,max=55
*p=1
p[0]=1

 课后习题:

二、字符类型

视频1:字符类型

字符类型

  • char是一种整数,也是一种特殊的类型——字符,因为:
  • 用单引号表示的字符字面量’a’,‘2’
  • ''也是一种字符
  • printf和scanf可以用%c来输入输出字符。

字符的输入输出

  • 如何输出'1'这个字符给char c?

#include<stdio.h>
int main(){
    char c;
    char d;
    c=1;
    d='1';
    if(c==d){
        printf("相等\n");
    }else{
        printf("不相等\n");
    }
       printf("%d",c);
       printf("%d",d);
       return 0;
   }

 不相等

1

49

 字符的输入输出

  • 如何输入'1'这个字符给char a?
    • scanf("%c",&c);——> 1
    • scanf("%d",&i);——> 49
#include<stdio.h>
int main(){
char c;
scanf("%c",&c);
printf("%d\n",c);
printf("%c\n",c);
return 0;
}

 输入:1

输出:49

          1

#include<stdio.h>
int main(){
int i;
char c;
scanf("%d",&i);
c=i;
printf("%d\n",c);
printf("'%c'\n",c);
return 0;
}

输入:1

输出:1

            ' '

  • '1'的ASCII编码是49,所以当c==49时,它代表'1'

混合输入

  • 有何不同
    • scanf("%d %c",&i,&c);
    • scanf("%d%c",&i,&c);

 带不带空格

#include<stdio.h>
int main(){
int i;
char c;
scanf("%d %c",&i,&c);
printf("i=%d,c=%d,c='%c'\n",i,c,c);
return 0;
}

如果带了空格,他会读入一个整数,然后空格几个都不要紧,然后再读入一个字符。

如果没有空格,他就会把空格当作下一个字符读进去。

字符计算

  • 一个字符加一个数字得到ASCII码表中的那个数之后的数字
  • 两个字符的减,得到它们在表中的距离

大小写转换

  • 字母在ASCII表中是顺序排列的
  • 大写字母和小写字母是分开排列的,并不在一起
  • 'a'-'A'可以得到两端之间的距离,于是
    • a+'a'-'A'可以把一个大写字母变成小写字母
    • a+'A'-'a'可以把一个小写字母变成大写字母

视频2:逃逸字符

 

 \t

 

 \b

三、字符串

视频1:字符串

字符数组
如果我们定义了这样的一个字符数组

char word[] = {'H','e','l','l','o','!'};

word[0]H
word[1]e
word[2]l
word[3]l
word[4]o
word[5]!

{}大括号是用来初始化这个数组,这样的字符数组里有很多的字符连起来,但是它不是C语言的字符串,因为不能用字符串的方式做运算。它只是字符数组

那么如何定义一个字符串了,我们则需要这样

char word[] = {'H','e','l','l','o','!','\0'};

word[0]H
word[1]e
word[2]l
word[3]l
word[4]o
word[5]!
word[6]\0

我们在初始化的最后加上了\0,这个\0就是一个C语言的字符串,可以进行运算

字符串

· 以0(整数0)解维的一串字符
·         0或’\0’是一样的,但是和’0’不同,单引号里的0表达的是asc码里面的 0, 而\0它是整数0
· 0 是用来标值字符串的结束,但是它本身不是字符串的一部分
        · 计算字符串长度的时候不包括这个0
· 字符串以数组的形式存在,访问时,它可以是数组,也可以是指针
·         更多时候访问是以指针的形式访问
· string.h 里有很多处理字符串的函数

字符串变量

字符串变量写法的的表现形式,通常有以下几种

· char *str = "Hello";	// str指针指向一个字符数组,里面放的内容是“Hello".
· char word[] = "Hello";		
· char line[10] = "Hello";	//有数组line,有10个字节大小,
//在里面放了“Hello”.占据6个位置,因为字符串结尾还有个0(编译器自动生成)

字符串常量

· “Hello”
· "Hello"会被编译器变成一个字符数组放在内存里,这个数组的长度是6,结尾还有表示结束的0
· 在C语言中,如何有两个相连的字符串,并没有任何结束时,会自己将他们联系起来

字符串
· C语言的字符串是以字符数组的形态存在的
· 不能用运算符对字符串做运算
· 通过数组的方式可以遍历字符串
· 唯一的特殊地方是字符串字面量可以用来初始化字符数组
· 标准库提供了一系列字符串函数

视频2:字符串变量

字符串常量

char* s = "Hello,world!"

#include<stdio.h>

int main(void) {
	char *s = "Hello World";
	s[0] = 'B';

	printf("Here!s[0]=%c\n", s[0]);
	return 0;
}

我在这里编译时会报错,老师这里竟然时通过的,网上查了下,有两种方案,有几种方案,我是用了const 改变为常量

    [Warning] deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

#include<stdio.h>

int main(void) {
	const char *s ="Hello World";
	//s[0] = 'B';
	const char *s2 ="Hello World";
	
	printf("s=%p\n", s);
	printf("s2=%p\n", s2);
	printf("Here!s[0]=%c\n", s[0]);
	return 0;
} 

输出结果:

s=00404000
s2=00404000
Here!s[0]=H

从这里我们可以看出,他们在内存中的地址是一样的,我们再添加一个i

#include<stdio.h>

int main(void) {
	int i=0;
	const char *s ="Hello World";
	//s[0] = 'B';
	const char *s2 ="Hello World";
	
	printf("i=%p\n", &i);
	printf("s=%p\n", s);
	printf("s2=%p\n", s2);
	printf("Here!s[0]=%c\n", s[0]);
	return 0;
} 

    i=0062FE94
    s=00404000
    s2=00404000
    Here!s[0]=H

这里可以看出i的地址比s和s2的地址要大很多,i是本地变量,它比较大,而s和s2很小它们存放在内存中的代码段
并且是只读属性,所以刚才我们那里有报错,因为是只读的不可修改的

字符串常量

char* s =“Hello World”;
· s是一个指针,初始化为指向一个字符串常量;
· 由于这个常量所在的地方,实际上s是const char* s,但是由于历史原因,IDE接受不带const的写法
· 但是视图对s所指的字符串写入,会导致严重后果
· 如果想要修改字符串,应该用数组

char s[ ] =“Hello World”;

下面我们来试试
 

#include<stdio.h>

int main(void) {
	int i=0;
	const char *s ="Hello World";
	//s[0] = 'B';
	const char *s2 ="Hello World";
	char s3[] = "Hello World";
	
	
	printf("i=%p\n", &i);
	printf("s=%p\n", s);
	printf("s2=%p\n", s2);
	printf("s3=%p\n", s3);
	s3[0] = 'B';
	printf("Here!s3[0]=%c\n", s3[0]);
	return 0;
} 

输出结果:

i=0062FE94
s=00404000
s2=00404000
s3=0062FE88
Here!s3[0]=B

我们看到s3也在一个比较大的地方,同时也是可以修改的
那么,当我们需要一个字符串的时候,我们该如何写了?

指针还是数组


· char *str = “Hello”;
· char word[] = “Hello”;
· 数组:这个字符串在内存固定区域地址
· 作为本地变量空间会被自动回收的
· 指针:这个字符串不知道在内存那一块
· 处理参数
· 动态分配内存空间

从这里可以得出:
如果要构造一个字符串,需要用数组
如果要处理一个字符串,需要用指针

char*是不是字符串

· 字符串可以表达char*的形式
· char*不一定是字符串
· 本意是指向字符的指针,可能指向的是字符的数组(就像int*一样)
· 只有它所指的字符数组有结尾的\0,才能说明它所指的是字符串

四、字符串计算

视频1:字符串输入与输出

字符串赋值?

  • char *t = "title";
  • char *s;
  • s = t;
  • 并没有产生新的字符串,只是让指针s指向了t所指的字符串,对s的任何操作就是对t做的

字符串的输入与输出

  • char string[8];
  • scanf("%s",string);
  • printf("%s",string);
  • scanf读入一个单词(到空格,tap或回车为止)
  • scanf是不安全的,因为不知道要读入的内容长度
#include <stdio.h> 

int main(void)
{
	char word[8];
    char word2[8];
    scanf("%s",word);
    scanf("%s",word2);
	printf("%s##%s##\n", word,word2);

	return 0;
 } 

安全的输入

  • char string[8];
  • scanf("%7s",string);
  • 在%和s之间的数字表示最多允许读入的字符的数量,这个数字应该比数组的大小小一些
  • 下一次的scanf从哪里开始?

常见错误

  • char *string;
  • scanf("%s",string);
  • 以为char*是字符串类型,定义了一个字符串类型的变量string就可以直接使用了
  • 由于没有对string初始化,所以不一定每次运行都出错

空字符串

  • char butter[100] = “ ”;
  • 这是一个空的字符串,butter[0] == '\0'
  • char butter [] = " ";
  • 这个数组的长度只有1!
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值