深⼊理解指针(5)【深入理解指针,体会大厂的笔试题】

在这里插入图片描述

1. sizeof和strlen的对⽐

1.1 sizeof

在学习操作符的时候,我们学习了sizeof ,sizeof 计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。

sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。

#inculde <stdio.h>
 int main()
 {
 int a = 10;
 printf("%d\n", sizeof(a));
 printf("%d\n", sizeof(int));
 return 0;
 }

在这里插入图片描述

1.2 strlen

strlen 是C语⾔库函数,功能是求字符串⻓度。函数原型如下:

size_t strlen ( const char * str );

统计的是从 strlen 函数的参数 str 中这个地址开始向后,\0之前字符串中字符的个数。

strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找。

> #include <stdio.h>
 int main()
 {
 char arr1[3] = {'a', 'b', 'c'};
 char arr2[] = "abc";
 printf("%d\n", strlen(arr1));
 printf("%d\n", strlen(arr2));
  return 0;
 }

在这里插入图片描述

1.3 sizeof 和strlen的对⽐

sizeof

  1. sizeof是操作符
  2. sizeof计算操作数所占内存的⼤⼩,单位是字节
  3. 不关注内存中存放什么数据

strlen

  1. strlen是库函数,使⽤需要包含头⽂件 string.h
  2. srtlen是求字符串⻓度的,统计的是 \0 之前字符的个数
  3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能会越界

2. 数组和指针笔试题解析★★★★★

2.1 ⼀维数组

int a[] = {1,2,3,4};
printf(“%d\n”,sizeof(a));
printf(“%d\n”,sizeof(a+0));
printf(“%d\n”,sizeof(* a));
printf(“%d\n”,sizeof(a+1));
printf(“%d\n”,sizeof(a[1]));
printf(“%d\n”,sizeof(&a));
printf(“%d\n”,sizeof(* &a));
printf(“%d\n”,sizeof(&a+1));
printf(“%d\n”,sizeof(&a[0]));
printf(“%d\n”,sizeof(&a[0]+1));

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a56ce8ebbdbf473e915a768d8da6aca6.png

解析:

  1. sizeof ( a ) , a是数组名,计算的是整个数组的大小,数组的类型是 int ,数组中有4个元素,每个元素(类型 int )占4个字节。所以是 4 * 4=16
  2. sizeof ( a + 0 ) ,首先要考虑 a+0 是什么?这个问题很重要。我们知道 sizeof ( 数组名 )表示的是整个数组,但是这里是 a+0 ,所以就不是数组名,a 表示的是首元素的地址,a+0 也就是首元素的地址(等价与 & a [0] ),所以sizeof ( a + 0)计算的是地址的大小。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  3. sizeof ( * a ) , a 没有单独放在 sizeof 内部,所以 a 是首元素的地址,* 是解引用,* a 表示的是首元素,一个字节,所以是 4
  4. sizeof ( a + 1 ) , a是首元素的地址( & a [ 0 ]------int* ) , +1—> & a[1] , 也就是第二个元素的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  5. sizeof ( a [1] ) , 表示的是计算第二个元素的大小,所以是4个字节。
  6. sizeof ( &a ) , &a 表示的是整个数组的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  7. sizeof ( * &a ) , &a 表示的是整个数组的地址,解引用一下表示的是整个数组,数组的类型是 int ,数组中有4个元素,每个元素(类型 int )占4个字节。所以是 4 * 4=16
  8. sizeof ( &a+1 ) ,&a=int ( *p ) [4] , *p 访问的是一个数组的大小, p+1 跳过一个数组的大小。所以 &a+1 应该是跳过整个数组,访问的是4后面的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  9. sizeof( &a[0] ) ,&a[0] 表示的是首元素的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  10. sizeof( &a[0]+1 ) ,&a[0]+1==&a[1] ,表示的是第二个元素的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)

2.2 字符数组

代码一:

char arr[] = {‘a’,‘b’,‘c’,‘d’,‘e’,‘f’};
printf(“%d\n”, sizeof(arr));
printf(“%d\n”, sizeof(arr+0));
printf(“%d\n”, sizeof(*arr));
printf(“%d\n”, sizeof(arr[1]));
printf(“%d\n”, sizeof(&arr));
printf(“%d\n”, sizeof(&arr+1));
printf(“%d\n”, sizeof(&arr[0]+1));

在这里插入图片描述

解析:

  1. sizeof ( arr ) , 表示的是整个数组的大小,是 char 类型,每个元素占1个字节。所以 1 * 6=6
  2. sizeof ( arr+0 ) , 首先要考虑 arr+0 是什么?这个问题很重要。我们知道 sizeof ( 数组名 )表示的是整个数组,但是这里是 arr+0 ,所以就不是数组名,arr 表示的是首元素的地址,arr+0 也就是首元素的地址(等价与 & a [0] ),所以sizeof ( a + 0)计算的是地址的大小。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  3. sizeof ( * arr ) , a 没有单独放在 sizeof 内部,所以 a 是首元素的地址,* 是解引用,* a 表示的是首元素,一个字节,所以是 1
  4. sizeof ( arr[1] ) , 表示的是计算第二个元素的大小,所以是1个字节。
  5. sizeof ( &arr ) , &arr 表示的是整个数组的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  6. sizeof ( &arr+1 ) , &arr+1 应该是跳过整个数组,访问的是 f 后面的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  7. sizeof ( &arr[0]+1) , &arr[0]+1==&arr[1] ,表示的是第二个元素的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)

代码二:

char arr[] = {'a','b','c','d','e','f'};
 printf("%d\n", strlen(arr));
 printf("%d\n", strlen(arr+0));
 printf("%d\n", strlen(*arr));
 printf("%d\n", strlen(arr[1]));
 printf("%d\n", strlen(&arr));
 printf("%d\n", strlen(&arr+1));
 printf("%d\n", strlen(&arr[0]+1));

size_t strlen(const char* )

解析:

  1. strlen (arr) , 随机值。因为 strlen 是遇到 \0 后停止,无法确定 \0 的位置,所以无法确定。
  2. strlen(arr+0) , 随机值。arr 表示的是首元素的地址,arr+0 也就是首元素的地址(等价与 & a [0] ),因为 strlen 是遇到 \0 后停止,无法确定 \0 的位置,所以无法确定。
  3. strlen( * arr) , 非法访问。arr 是首元素的地址,*arr 是 ‘a’ , a的ASCII编码是97,所以就会把97当成地址来访问。(理解strlen的参数)
  4. strlen(arr[1]) , 非法访问。arr 是首元素的地址,arr[1]==‘b’ , b的ASCII编码是98,所以就会把98当成地址来访问。(理解strlen的参数)
  5. strlen(&arr) , 随机值。&arr是整个数组的地址,也就是首元素的地址。&arr的类型是 char (*p)[6] 数组指针类型,但是strlen的参数类型是const char *类型,这里编译器就会自动转化,所以就不用考虑类型不匹配问题。因为 strlen 是遇到 \0 后停止,无法确定 \0 的位置,所以无法确定。
  6. strlen(&arr+1) , 随机值。&arr是整个数组的地址,也就是首元素的地址。&arr+1表示的是跳过整个数组,指针指向f后面的位置。因为 strlen 是遇到 \0 后停止,无法确定 \0 的位置,所以无法确定。
  7. strlen(&arr[0]+1) , 随机值。&arr[0]表示的是数组首元素的地址,&arr[0]+1就是b的地址,因为 strlen 是遇到 \0 后停止,无法确定 \0 的位置,所以无法确定。

代码三:

>  char arr[] = "abcdef";
 printf("%llu\n", sizeof(arr));
 printf("%llu\n", sizeof(arr+0));
 printf("%llu\n", sizeof(*arr));
 printf("%llu\n", sizeof(arr[1]));
 printf("%llu\n", sizeof(&arr));
 printf("%llu\n", sizeof(&arr+1));
 printf("%llu\n", sizeof(&arr[0]+1));

解析:

  1. sizeof(arr) , 7。sizeof不关心里面的内容,只在乎占了多大的空间。sizeof(arr)表示的是整个数组的大小,是 char 类型,每个元素占1个字节。所以 1 * 7=7
  2. sizeof(arr+0) ,4/8。 首先要考虑 a+0 是什么?这个问题很重要。我们知道 sizeof ( 数组名 )表示的是整个数组,但是这里是 a+0 ,所以就不是数组名,a 表示的是首元素的地址,a+0 也就是首元素的地址(等价与 & a [0] ),所以sizeof ( a + 0)计算的是地址的大小。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  3. sizeof(arr) ,1。 a 没有单独放在 sizeof 内部,所以 a 是首元素的地址, 是解引用,* a 表示的是首元素,一个字节,所以是 1
  4. sizeof(arr[1]), 表示的是计算第二个元素的大小,所以是1个字节。
  5. sizeof(&arr), &arr 表示的是整个数组的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  6. sizeof(&arr+1), &arr+1 应该是跳过整个数组,访问的是 f 后面的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  7. sizeof(&arr[0]+1), &arr[0]+1==&arr[1] ,表示的是第二个元素的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)

代码四:

char arr[] = "abcdef";
 printf("%d\n", strlen(arr));
 printf("%d\n", strlen(arr+0));
 printf("%d\n", strlen(*arr));
 printf("%d\n", strlen(arr[1]));
 printf("%d\n", strlen(&arr));
 printf("%d\n", strlen(&arr+1));
 printf("%d\n", strlen(&arr[0]+1));

解释:

  1. strlen(arr), 6。因为 strlen 是遇到 \0 后停止,所以就是6。
  2. strlen(arr+0),6。arr 表示的是首元素的地址,arr+0 也就是首元素的地址(等价与 & a [0] ),因为 strlen 是遇到 \0 后停止,所以就是6。
  3. strlen(*arr), 非法访问。arr 是首元素的地址,*arr就是’a’ , a的ASCII编码是97,所以就会把97当成地址来访问。(理解strlen的参数)
  4. strlen(arr[1]), 非法访问。arr 是首元素的地址,arr[1]==‘b’ , b的ASCII编码是98,所以就会把98当成地址来访问。(理解strlen的参数)
  5. strlen(&arr),&arr是整个数组的地址,也就是首元素的地址。&arr的类型是 char (*p)[6] 数组指针类型,但是strlen的参数类型是const char *类型,这里编译器就会自动转化,所以就不用考虑类型不匹配问题。因为 strlen 是遇到 \0 后停止,所以就是6。
  6. strlen(&arr+1),随机值。&arr是整个数组的地址,也就是首元素的地址。&arr+1表示的是跳过整个数组,指针指向 \0 后面的位置。因为 strlen 是遇到 \0 后停止,无法确定 \0 的位置,所以无法确定。
  7. strlen(&arr[0]+1),5。 &arr[0]表示的是数组首元素的地址,&arr[0]+1就是b的地址,因为 strlen 是遇到 \0 后停止,所以就是5。

代码五:

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

解释:
注意:
*p表示的是a(首元素),
p表示的是a(首元素)的地址

  1. sizeof( p),p表示的是a(首元素)的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  2. sizeof(p+1),p+1表示的是b的地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  3. sizeof(*p),*p表示的是a(首元素),所以是1字节
  4. sizeof(p[0]),p[0]表示的是a(首元素),所以是1字节
  5. sizeof(&p),&p表示的是P的地址,(注意:p本身也是有地址,p存储空间里存放的是a的地址),,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  6. sizeof(&p+1),&p表示的是P的地址,(&p+1)表示的是跳过一个P的地址,指针指向下一个地址。是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  7. sizeof(&p[0]+1),&p[0]表示的是a的地址,&p[0]+1表示的是b的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)

代码六:

 char *p = "abcdef";
 printf("%d\n", strlen(p));
 printf("%d\n", strlen(p+1));
 printf("%d\n", strlen(*p));
 printf("%d\n", strlen(p[0]));
 printf("%d\n", strlen(&p));
 printf("%d\n", strlen(&p+1));
 printf("%d\n", strlen(&p[0]+1));

解释:
注意:
*p表示的是a(首元素),
p表示的是a(首元素)的地址

  1. strlen( p),p表示的是a(首元素)的地址,因为 strlen 是遇到 \0 后停止,所以就是6。
  2. strlen(p+1),p表示的是a(首元素)的地址,p+1表示的是b的地址,因为 strlen 是遇到 \0 后停止,所以就是5。
  3. strlen(*p), 非法访问。*p表示的是a(首元素), a的ASCII编码是97,所以就会把97当成地址来访问。(理解strlen的参数)
  4. strlen(p[0]), 非法访问。p[0]表示的是a(首元素),a的ASCII编码是97,所以就会把97当成地址来访问。(理解strlen的参数)
  5. strlen(&p),随机值。&p表示的是P的地址,(注意:p本身也是有地址,p存储空间里存放的是a的地址),因为 strlen 是遇到 \0 后停止,所以无法确定。
  6. strlen(&p[0]+1),5。&p[0]表示的是a的地址,&p[0]+1表示的是b的地址,因为 strlen 是遇到 \0 后停止,所以5字节。

2.3 ⼆维数组

> int a[3][4] = {0};
 printf("%d\n",sizeof(a));
 printf("%d\n",sizeof(a[0][0]));
 printf("%d\n",sizeof(a[0]));
  printf("%d\n",sizeof(a[0]+1));
 printf("%d\n",sizeof(*(a[0]+1)));
 printf("%d\n",sizeof(a+1));
 printf("%d\n",sizeof(*(a+1)));
 printf("%d\n",sizeof(&a[0]+1));
 printf("%d\n",sizeof(*(&a[0]+1)));
 printf("%d\n",sizeof(*a));
 printf("%d\n",sizeof(a[3]));

解释:

  1. sizeof(a),计算的是整个二维数组的大小,3* 4* 4 =48,单位字节
  2. sizeof(a[0][0]),计算的是第一行第一个元素,4个字节
  3. sizeof(a[0]),a[0]表示的是第一行的数组名,数组名单独放在sizeof里面,计算的是第一行的大小,4* 4=16,单位字节
  4. sizeof(a[0]+1),a[0]没有单独放在sizeof里面,所以这里表示的是第一行第一个元素的地址,所以a[0]+1表示的是第一行第二个元素的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  5. sizeof(*(a[0]+1)),a[0]没有单独放在sizeof里面,所以这里表示的是第一行第一个元素的地址,所以a[0]+1表示的是第一行第二个元素的地址,解引用,*(a[0]+1)表示的是表示的是第一行第二个元素,4个字节
  6. sizeof(a+1),a 没有单独放在sizeof里面,也没有&,所以这里a表示的是数组首元素的地址,也就是第一行的地址。a+1表示的是第二行的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  7. sizeof(*(a+1)),(a+1)表示的是第二行的地址,*(a+1)==a[1] 表示的是第二行的数组名,所以数组名单独放在sizeof里面,计算的是第二行的大小,4 * 4=16
  8. sizeof(&a[0]+1),a[0]表示的是第一行的数组名,&a[0]表示的是第一行的地址,&a[0]+1表示的是第二行的地址,是地址就是4个或8个字节。(x86 4个字节,x64 8个字节)
  9. sizeof(*(&a[0]+1)),&a[0]+1表示的是第二行的地址, * (&a[0]+1)表示的是第二行,计算的是第二行的大小,4 * 4=16
  10. sizeof(*a),a表示的是数组首元素的地址,也就是第一行的地址。*a表示的是第一行,计算的是第一行的大小,4 * 4=16
  11. sizeof(a[3]),这里不是报错,也不是越界访问,编译器会把a[3]看成是数组名,相当于arr[0],所以就是16

数组名的意义:

  1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
  2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表⽰⾸元素的地址。

3. 指针运算笔试题解析★★★★★

3.1 题⽬1:

#include <stdio.h>
 int main()
 {
 int a[5] = { 1, 2, 3, 4, 5 };
 int *ptr = (int *)(&a + 1);
 printf( "%d,%d", *(a + 1), *(ptr - 1));
 return 0;
 }

程序的结果是什么?

解析:

  • *(a + 1),a表示的是数组的首元素的地址,a+1就是 2 的地址,所以 * (a + 1)解引用表示的是2
  • *(ptr - 1), &a表示的是整个数组的地址,&a + 1表示的是指针指向整个数组的后面,也就是5的后面的地址。(int *)(&a + 1)这里进行了int *的强制类型转化, 所以 *ptr就是表示5后面的内存空间。ptr - 1就是5的地址, * (ptr - 1)就是5。

3.2 题⽬2

struct Test
 {
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
 }*p = (struct Test*)0x100000;

 int main()
 {
 printf("%p\n", p + 0x1);
 printf("%p\n", (unsigned long)p + 0x1);
 printf("%p\n", (unsigned int*)p + 0x1);
 return 0;
 }

在X86环境下,假设结构体的⼤⼩是20个字节,程序输出的结构是啥?

解析:
分析:p是指针变量,不是类型,地址是0x100000

  1. p + 0x1,p是指针变量,不是类型,所以p+1就是跳过一个结构体,结构体的⼤⼩是20个字节,地址是0x100000,加上20就变成0x100014
  2. (unsigned long)p + 0x1,p是指针变量,(unsigned long)p强制转换成long类型,类型加1,就是加1,所以结果是0x100001
  3. (unsigned int * )p + 0x1,p是指针变量,(unsigned int*)p表示的是强制转换成int* 型,指针类型+1表示的是跳过一个指针类型,所以结果就是0x100004

3.3 题⽬3

 #include <stdio.h>
 int main()
 {
 int a[3][2] = { (0, 1), (2, 3), (4, 5) };
 int *p;
 p = a[0];
 printf( "%d", p[0]);
 return 0;
 }

解析:
分析:int a[3][2] = { (0, 1), (2, 3), (4, 5) };这是什么?
这是逗号表达式,从左向右计算,从整体上最后的结果为右边的表达式
所以 int a[3][2] ={1,3,5}

  1. p[0],p = a[0]=&a[0][0],p[0]==a[0][0],所以就是1

3.4 题⽬4

#include <stdio.h>
 int main()
 {
 int a[5][5];
 int(*p)[4];
 p = a;
 printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
 return 0;
 }

假设环境是x86环境,程序输出的结果是啥?

解析:

  1. &p[4][2] - &a[4][2],如下图所示,地址-地址=中间的元数个数=-4
    【-4】原:10000000 00000000 00000000 00000100
    【-4】反:111111111 111111111 111111111 111111011
    【-4】补:111111111 111111111 111111111 111111100
    【-4】16进制:F F F F F F F C
    因为输出格式%p,所以就是FFFFFFFC
  2. &p[4][2] - &a[4][2],输出格式%d,所以就是-4

在这里插入图片描述

3.5 题⽬5

 #include <stdio.h>
 int main()
 {
 int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 int *ptr1 = (int *)(&aa+1);
 int *ptr2 = (int *)(*(aa + 1));
 printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
 return 0;
 }

解析:

  1. *(ptr1 - 1),&aa取出的是整个数组的地址,&aa+1就是跳过整个数组,指针指向整个数组的后面,(int *)(&aa+1)进行类型的强转赋给 *ptr1,所以ptr1存储的就是&aa+1的地址,ptr1 - 1表示的就是10的地址, * (ptr1 - 1)就是10。
  2. (ptr2 - 1),aa表示的是首元素的地址,也就是第一行的地址,aa + 1就是跳过第一行,指针指向第二行的地址, * (aa + 1)就是6,(int * )((aa + 1)进行类型的强转,ptr2就是6的地址,ptr2 - 1就是5的地址,所以 *(ptr2 - 1)就是5

3.6 题⽬6

 #include <stdio.h>
 int main()
 {
 char *a[] = {"work","at","alibaba"};
 char**pa = a;
 pa++;
 printf("%s\n", *pa);
 return 0;
 }

解释:
char *a[] = {“work”,“at”,“alibaba”};
注意:并不是把字符串放到数组中去,而是把字符串的首字母放到数组中去。
所以 a是第一行的地址,放到了pa中, pa++,指针也就指向了第二行
所以 *pa就是at

3.7 题⽬7

#include <stdio.h>
 int main()
 {
 char *c[] = {"ENTER","NEW","POINT","FIRST"};
 char**cp[] = {c+3,c+2,c+1,c};
 char***cpp = cp;
 printf("%s\n", **++cpp);
 printf("%s\n", *--*++cpp+3);
 printf("%s\n", *cpp[-2]+3);
 printf("%s\n", cpp[-1][-1]+1);
 return 0;
 }

解析:
char *c[] = {“ENTER”,“NEW”,“POINT”,“FIRST”};
char**cp[] = {c+3,c+2,c+1,c};
char ***cpp = cp;
如图所示:
在这里插入图片描述

  1. ** ++cpp,cpp指向的是 cp中F的地址,++cp指针指向**cp 中p,*cp是p,cp指针指向c中的p,所以cp就是POINT
  2. ** ++cpp+3 **,根据上一步可知,cpp指向的是cp中p的地址,++cpp指向的是 * * cp中N(c+1)的地址,*++cpp就是c中的N,-- *++cpp指向c中的E, ** * – *++cpp就是ENTER,但是这时候指针指向的是E,+3就变成指向T后面的E,所以结果就是打印ER
  3. *cpp[-2]+3,根据上一步可知,cpp指向的是 cp中N的地址,*cpp[-2]= **(cpp-2),所以cpp指向的是 * * cp中F(c+3)的地址,*cpp[-2]就表示c中的F,+3指针就指向S,所以打印的结果就是ST
  4. cpp[-1][-1]+1,cpp[-1][-1]+1=* ( *(cpp-1)-1)+1,注意:cpp[-2]不会改变指针,根据上上一步可知,cpp指向的是 cp中N的地址,cpp-1指向cp中p的地址, * (cpp-1)指针指向c中的N的地址, * ( *(cpp-1)-1)就是c中的NEW,+1指针冲N指向E,所以打印结果就是EW

文章到这就结束了~~
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值