掘根宝典之c语言字符指针,指针数组,数组指针,函数指针

目录

字符指针

字符指针指向字符串

使用字符指针

例子

指针数组

数组指针

数组名和&数组名 

数组名

sizeof(数组名),&数组名

&数组名

&数组名错误使用方法

数组名和&数组名用于一维数组

例子1

例子2

  数组名和&数组名用于二维数组

例子1

例子2

函数指针

通过函数指针调用函数


字符指针

在C语言中,字符指针是一种特殊的指针类型,用于指向字符数据的内存地址。

字符指针的声明形式为:

 char *字符指针名=字符串/字符串;

这种形式在c语言是允许的,但是c++禁止char*指针指向常量字符串

字符指针指向字符串

 char* str = "Hello,World!"; 

这意味着将字符串的首字符的地址赋给字符指针

我们可以验证一下

#include<stdio.h>
int main()
{
     char* str = "Hello,World!"; 

    printf("%p\n", str); 
    printf("%p\n", "Hello,World!"); 
    printf("%p\n", &str[0]);
    printf("%c\n", str[0]);

   
}

结果

事实证明确实如此

使用字符指针

使用字符指针时,有几个需要注意的地方:

  1. 字符指针的初始化:在定义字符指针时,可以直接赋值一个字符串常量,也可以通过动态内存分配来初始化指针。例如:

    char *str1 = "Hello World"; // 字符指针指向字符串常量
    char *str2 = malloc(20);    // 字符指针指向动态分配的内存
    

    注意,字符串常量是不可修改的,所以使用字符指针指向字符串常量时要谨慎,确保不会试图修改字符串。

  2. 字符指针的解引用:使用字符指针访问字符串中的字符时,可以使用指针自增运算符 ++ 来实现。例如:

    char *str = "Hello";
    while (*str) {
        printf("%c", *str++);
    }
    

    这里的 *str++ 先取出 str 指针指向的字符,然后将指针自增,指向下一个字符。

  3. 字符指针的比较:可以使用比较运算符 ==!=&lt;>&lt;=>= 来比较字符指针的大小。例如

    char *str1 = "apple";
    char *str2 = "banana";
    printf("%d", str1 < str2); // 输出1,表示str1在str2之前
    

    字符指针的比较是基于内存地址的,指向内存地址较低的字符指针比较小。

  4. 字符指针的修改:字符指针可以通过赋值来修改指向的字符串。但是,如果字符指针指向的是字符串常量,则不能修改指针指向的内容。例如:

    char *str = "Hello";
    str[0] = 'h'; // 错误,试图修改字符串常量
    

    如果需要修改字符串,可以使用字符数组来替代字符指针。

  5. 字符指针的空指针检查:在使用字符指针之前,建议先进行空指针检查。例如:

    char *str = NULL;
    if (str == NULL) {
        printf("Pointer is NULL\n");
    }
    

    避免在空指针上进行解引用操作,以防止程序崩溃或产生未定义行为。

例子

可以使用字符指针来访问字符串和字符数组,例如:

#include <stdio.h>

int main() {
    char *str = "Hello, World!";  // 字符串常量
    char arr[] = "Hello, World!"; // 字符数组

    printf("%s\n", str);  // 输出字符串
    printf("%c\n", *str); // 输出第一个字符

    printf("%s\n", arr);  // 输出字符数组
    printf("%c\n", arr[0]); // 输出第一个字符

    return 0;
}

结果

指针数组

在C语言中,指针数组是指一个数组,其每个元素都是指针类型的变量。

指针数组可以用于存储一组指针,每个指针可以指向不同的数据。

指针数组的声明方式为:

指针类型 *数组名[数组大小]

以下是一个指针数组的示例:

int main() {
    int num1 = 10, num2 = 20, num3 = 30;
    int *ptrArray[3]; // 声明一个包含3个int类型指针的数组

    ptrArray[0] = &num1; // 指针数组的第一个元素指向num1
    ptrArray[1] = &num2; // 指针数组的第二个元素指向num2
    ptrArray[2] = &num3; // 指针数组的第三个元素指向num3

    printf("%d\n", *ptrArray[0]); // 输出10,访问指针数组的第一个元素所指向的值
    printf("%d\n", *ptrArray[1]); // 输出20,访问指针数组的第二个元素所指向的值
    printf("%d\n", *ptrArray[2]); // 输出30,访问指针数组的第三个元素所指向的值

    return 0;
}

在上述示例中,声明了一个包含3个int类型指针的指针数组ptrArray。然后,通过将指针数组的元素指向各个变量,可以实现对这些变量的间接访问。通过解引用操作符 * 和数组下标,可以访问对应元素所指向的值。

指针数组在实际应用中有很多用途,比如可以用来存储字符串数组、函数指针数组等。

数组指针

在C语言中,数组指针是指一个指向数组的指针变量。

数组指针可以用来访问数组元素,也可以用来处理多维数组。

数组指针的声明方式为:

数据类型 (*指针变量名)[数组大小];

数组名和&数组名 

在C语言中,&数组名数组名的运算结果是不同的。

数组名

在C语言中,数组名是一个特殊的标识符,大多数情况下它表示数组的首元素的地址。

当使用数组名时,它会自动转换为指向数组第一个元素的指针。这意味着可以通过数组名来访问数组中的元素。

下面是一个示例代码来说明数组名的用法:

#include <stdio.h>

int main() {
    int numArray[5] = {1, 2, 3, 4, 5};

    printf("%p\n", numArray); // 输出数组的首地址
    printf("%p\n",&numArray[0]);
    return 0;
}

输出结果如下:

0x7fff5a40ce90
0x7fff5a40ce90

可以看到,numArray输出的是数组的首地址。

在一些情况下,可以将数组名用作指针来访问数组元素。例如,可以使用numArray[0]来访问数组的第一个元素,使用numArray[1]来访问数组的第二个元素,依此类推。

需要注意的是,数组名作为指针时是常量,不能对其进行赋值操作。也就是说,不能将数组名指向另一个数组或另一个地址。

sizeof(数组名),&数组名

绝大多数情况下,数组名代表数组首元素地址

但是有两种例外情况,sizeof(数组名)和&数组名,这里的数组名都代表整个数组

 int numArray[5] = { 1, 2, 3, 4, 5 };

 printf("%d\n", sizeof(numArray)); 
 printf("%p\n", &numArray);// 输出整个数组的地址

 运行结果是

 

&数组名

&数组名:取得是整个数组的地址,也就是数组的首地址。

当使用&数组名时,它返回的是整个数组的指针,指向整个数组的存储空间

这与使用数组名(返回的是指向数组第一个元素的指针)有所不同。

&数组名一般用于二维指针

对于二维数组,&数组名表示整个二维数组的地址,二维数组的地址是数组首元素的地址,二维数组首元素是个数组。

所以&数组名,表示都是指向数组的指针

下面是一个示例代码来说明&数组名的用法:

#include <stdio.h>

int main() {
    int matrix[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

    printf("%p\n", &matrix);      // 输出整个二维数组的地址
    printf("%p\n", matrix);       // 输出二维数组的首行地址,也即第一个子数组的地址
    printf("%p\n", &matrix[0]);   // 输出二维数组的首行地址,与上一行等效
    printf("%p\n", matrix[0]);    // 输出二维数组的首行地址,与上两行等效
    printf("%p\n", &matrix[0][0]); // 输出二维数组的第一个元素的地址

    return 0;
}

输出结果如下:

0x7fff5a40ce90
0x7fff5a40ce90
0x7fff5a40ce90
0x7fff5a40ce90
0x7fff5a40ce90

可以看到,&matrixmatrix&matrix[0]matrix[0]&matrix[0][0]都输出了相同的地址,即整个二维数组的地址。

需要注意的是,二维数组的地址类型是指向一维数组的指针,即int (*)[3]。这是因为在内存中,二维数组是按行存储的,每行是一个一维数组。

因此,对于二维数组,&数组名表示整个数组的地址,数组名表示首行的地址,&数组名[0]数组名[0]表示第一行的地址,&数组名[0][0]表示第一个元素的地址。

总结起来,&数组名表示获取整个数组的地址,返回的是指向整个数组的指针。

&数组名错误使用方法

我们看个例子

int a[5]={1,2,3,4,5};
int(*p)[5]=&a;
printf("%d",*p);//这是错误的

p是指向数组的,*p相当于数组名,数组名又相当于数组首元素首地址,以%d打印出来就是一堆乱码

数组名和&数组名用于一维数组

例子1

下面是一个示例代码来说明这两者的区别:

#include <stdio.h>

int main() {
    int numArray[5] = {1, 2, 3, 4, 5};

    printf("%p\n", &numArray); // 输出数组的首地址
    printf("%p\n", numArray); // 输出数组的首地址
    printf("%p\n", &numArray[0]); // 输出数组的首地址

    printf("%p\n", &numArray + 1); // 输出整个数组占用的内存空间后面的地址
    printf("%p\n", numArray + 1); // 输出数组第二个元素的地址
    printf("%p\n", &numArray[1]); // 输出数组第二个元素的地址

    return 0;
}

输出结果如下:

0x7fffc7f12680
0x7fffc7f12680
0x7fffc7f12680
0x7fffc7f12694
0x7fffc7f12684
0x7fffc7f12684

可以看到,&numArraynumArray&numArray[0]的值都是相同的,都是数组的首地址。而&numArray + 1 是整个数组占用的内存空间后面的地址,而numArray + 1&numArray[1]是数组第二个元素的地址。

需要注意的是,当数组作为函数参数传递时,实际上传递的是数组的指针(首地址),而不是整个数组。这是因为数组在参数传递过程中会自动退化为指针。因此,函数名&函数名的结果是相同的,都是函数的地址。

总结起来,&数组名表示整个数组的地址,而数组名表示数组的首元素的地址。在大多数情况下,使用数组名会自动退化为指向第一个元素的指针。

例子2

以下是一个数组指针的示例:

int main() {
    int numArray[5] = {1, 2, 3, 4, 5};
    int (*ptr)[5]; // 声明一个指向包含5个int类型元素的数组的指针变量

    ptr = &numArray; // 数组指针指向numArray数组的首地址

    printf("%d\n", (*ptr)[0]); // 输出1,访问数组指针指向的数组的第一个元素
    printf("%d\n", (*ptr)[1]); // 输出2,访问数组指针指向的数组的第二个元素
    printf("%d\n", (*ptr)[2]); // 输出3,访问数组指针指向的数组的第三个元素

    return 0;
}

在上述示例中,声明了一个包含5个int类型元素的数组numArray。然后,声明了一个指向包含5个int类型元素的数组的指针变量ptr,并将其指向numArray数组的首地址。

通过解引用操作符 * 和圆括号来定义操作符优先级,可以访问数组指针指向的数组的元素。在示例中,使用(*ptr)[index]的方式访问数组元素,其中index表示要访问的元素的下标

  数组名和&数组名用于二维数组

int a[2][4]={{1,2,3,4},{5,6,7,8}};
int (*b)[4]=a;

二维数组数组名代表它第一行的地址

 此时a代表二维数组首元素地址,但二维数组首元素是个数组啊,所以此时b指向了一个一维数组

我们再看下面这种情况

int a[2][4]={{1,2,3,4},{5,6,7,8}};
int (*c)[4]=&a;

此时&a代表整个二维数组的地址,也就是说b接受了一个二维数组的地址,但是b是一维数组指针,所以&a被隐式转换为a第一个子数组的地址

我们可以来验证一下

 

我们可以看到啊,b,c完全是一样的,均指向a[0]这个数组的地址。

a的类型是int[2][4],赋给b时存在隐式类型转换

&a代表整个二维数组的地址,是int(*)[2][4],这与c的int(*)[4]不同,所以赋给c时也存在隐式转换

事实上

下面这种情况也是一样的道理

int a[2][4] = { {1,2,3,4},{5,6,7,8} };

int(*d)[2][4] = a;
int(*e)[2][4] = &a;

例子1

数组指针可以用于处理多维数组。例如,可以声明一个指向二维数组的指针来访问二维数组的元素。

int main() {
    int twoDimArray[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*ptr)[3]; // 声明一个指向包含3个int类型元素的数组的指针变量

    ptr = twoDimArray; // 数组指针指向twoDimArray二维数组的首地址

    printf("%d\n", (*ptr)[0]); // 输出1,(*ptr)代表twoDimArray[0]
    printf("%d\n", (*ptr)[1]); // 输出2,访问数组指针指向的二维数组的第二个元素
    printf("%d\n", (*ptr)[2]); // 输出3,访问数组指针指向的二维数组的第三个元素

    return 0;
}

这里的*ptr代表*(ptr+0),即twoDimArray[0]

在上述示例中,声明了一个包含2行3列的二维数组twoDimArray。然后,声明了一个指向包含3个int类型元素的数组的指针变量ptr,并将其指向twoDimArray数组的首地址。通过(*ptr)[index]的方式访问二维数组的元素。

数组指针在C语言中是一个灵活而强大的工具,可以用来处理数组和多维数组的访问和操作。

例子2
#include<stdio.h>
int main()
{
  
    int twoDimArray[2][3] = { {1, 2, 3}, {4, 5, 6} };
    int(*ptr)[3]; // 声明一个指向包含3个int类型元素的数组的指针变量

    ptr = &twoDimArray; // 这里存在隐式转换

    printf("%d\n", (*ptr)[0]); // 输出1,访问数组指针指向的二维数组的第一个元素
    printf("%d\n", (*ptr)[1]); // 输出2,访问数组指针指向的二维数组的第二个元素
    printf("%d\n", (*ptr)[2]);//输出3
}

这里的*ptr代表*(ptr+0),即twoDimArray[0]

结果

1
2
3

和上面那个例子一样

函数指针

C语言函数指针是指向函数的指针变量。它可以用来存储函数的地址,并且可以通过函数指针调用函数。

对于函数而言,函数名和&函数名都是函数的地址

函数指针的声明格式为:

返回类型 (*指针变量名)(参数类型1, 参数类型2, ...);

以下是一个简单的例子:

#include <stdio.h>

// 函数声明
int add(int a, int b);

int main() {
    // 定义函数指针变量
    int (*ptr)(int, int);
    
    // 将函数的地址赋值给指针变量
    ptr = add;
    
    // 通过指针调用函数
    int result = ptr(3, 4);
    
    printf("Result: %d\n", result);
    
    return 0;
}

// 函数定义
int add(int a, int b) {
    return a + b;
}

在上面的例子中,我们声明了一个名为ptr的函数指针变量,类型为int (*)(int, int),即指向一个具有两个int类型参数并返回int类型的函数。然后,我们将add函数的地址赋值给ptr,并通过ptr调用add函数,将结果打印出来。输出结果为7

函数指针在C语言中常用于实现回调函数、函数式编程等高级技术。它可以动态地决定需要调用哪个函数,提高了程序的灵活性和可扩展性。

通过函数指针调用函数

在C语言中,可以通过函数指针调用函数。具体步骤如下:

  1. 声明函数指针:首先需要声明一个函数指针,指定函数的返回类型和参数类型。例如,要声明一个指向返回类型为int,参数类型为int的函数的指针,可以这样写:int (*ptr)(int);

  2. 赋值函数地址:将要调用的函数的地址赋值给函数指针变量。例如,如果有一个名为add的函数,可以将其地址赋值给ptrptr = add;

  3. 通过函数指针调用函数:通过函数指针变量调用函数,可以像调用普通函数一样使用函数指针。通过使用指针变量的名称(加上括号和参数),可以调用所指向的函数。例如,可以使用ptr(3)来调用函数add(3)

下面是一个简单的例子来说明如何通过函数指针调用函数:

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

int main() {
    int (*ptr)(int, int);  // 声明函数指针
    
    ptr = add;  // 将add函数的地址赋给指针变量
    int result = ptr(3, 4);  // 通过指针变量调用add函数
    printf("Result of add: %d\n", result);
    
    ptr = multiply;  // 将multiply函数的地址赋给指针变量
    result = ptr(3, 4);  // 通过指针变量调用multiply函数
    printf("Result of multiply: %d\n", result);
    
    return 0;
}

输出结果为:

Result of add: 7
Result of multiply: 12

在上面的例子中,我们声明了一个名为ptr的函数指针变量,类型为int (*)(int, int),即指向一个具有两个int类型参数并返回int类型的函数。然后,我们将add函数和multiply函数的地址分别赋值给ptr,并通过ptr调用这两个函数。最后,将结果打印出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/426946.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

龙耀南街 喜闹元宵| 猜灯谜送汤圆蒙面K歌精彩多多!

上元南街,璀璨烟花!正月十五,你来南街闹元宵了吗? 为了更好的让游客体验碳水王国丰富多元的元宵活动,南街特此设定了:送汤圆做龙灯、猜灯谜送财气、大屏互动.好运连连、南街大舞台.有才你就来—蒙面歌王挑战赛、璀璨烟花,现场热闹欢腾~ 送汤圆: 做龙灯: 猜灯谜送财气: 大屏互…

Java内存区域

Java内存区域 Java内存区域就是Java运行时数据区 线程私有的&#xff1a;程序计数器、虚拟机栈、本地方法栈线程共享的&#xff1a;堆、方法区 1.程序计数器 程序计数器是什么&#xff1a;可以看作是当前线程所执行的字节码的行号指示器 程序计数器的作用&#xff1a; 实…

Open3D 进阶(21)无序点云平面检测的鲁棒统计方法

目录 一、算法原理1、算法过程2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、算法过程 除了寻找具有最大支持的单个平面外,Open3D还包含一个算法,该算法使…

于月仙主动与赵本山握手表示欢迎,赵:怎么着要跟我第二次牵手啊?

于月仙主动与赵本山握手表示欢迎&#xff0c;赵&#xff1a;怎么着要跟我第二次牵手啊&#xff1f; --小品《乡村爱情》&#xff08;中1&#xff09;的台词 表演者&#xff1a;赵本山 于月仙 王小利 唐鉴军等 &#xff08;接上&#xff09; 咱们呢就给新人揭盖头 好 好长贵…

STM32 (4) GPIO(1)

1.芯片的引脚分布 2.普通IO引脚的命名规则 3.IO复用 IO引脚身兼数职的现象叫做IO复用&#xff0c;可以使芯片拥有更多的功能&#xff0c;例如&#xff1a; PA9和PA10既可以用于GPIO的引脚&#xff0c;也可以用于串口或定时器的引脚 通用&#xff1a;CPU直接控制IO引脚的输入输…

Leetcode热题100道

Leetcode热题100道 &#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是 枫度柚子&#x1f341;&#xff0c;Java摆烂选手&#xff0c;很高兴认识大家 &#x1f440; &#x1f4d5;CSDN/掘金/B站: 枫吹过的柚 &#x1f341; &#x1f525;如果感觉博主的文章还不错的话&a…

FreeRTOS(一)FreeRTOS基础知识

目录 简单介绍 FreeRTOS基础知识 任务调度 抢占式调度&#xff1a; 举例说明&#xff1a; 时间片调度 举例说明 任务状态 FreeRTOS中4种任务状态 四种任务状态转换图 任务状态列表 今天开个新坑----FreeRTOS 简单介绍 FreeRTOS是一个轻量级的实时操作系统&#xf…

修复通达OA 百度ueditor 文件上传漏动

前些日子&#xff0c;服务器阿里云监控报警&#xff0c;有文件木马文件&#xff0c;因为非常忙&#xff0c;就没及时处理&#xff0c;直接删除了木马文件了事。 谁知&#xff0c;这几天对方又上传了木马文件。好家伙&#xff0c;今天不花点时间修复下&#xff0c;你都传上瘾了…

【风格迁移】对比度保持连贯性损失 CCPL:解决图像局部失真、视频帧间的连贯性和闪烁

对比度保持连贯性损失 CCPL&#xff1a;解决图像局部失真、视频帧间的连贯性和闪烁 提出背景解法&#xff1a;对比度保持连贯性损失&#xff08;CCPL&#xff09; 局部一致性假设 对比学习机制 邻域调节策略 互信息最大化对比学习&#xff1a;在无需标签的情况下有效学习区分…

【软件设计师】通俗易懂的去了解算法的时间复杂度

&#x1f413; 时间复杂度 常用排序的时间复杂度 时间频度 算法需要花费的时间&#xff0c;和它语句执行的次数是成正比的&#xff0c;所以会把一个算法种语句执行次数称为语句频度和时间频度、记作T(n)。 定义 时间复杂度就是找到一个无限接近时间频度T(n)同数量级的函数&am…

VMware安装DOS 7.1

VMware安装DOS 7.1 helpfasthelpdoshelp

【重温设计模式】职责链模式及其Java示例

职责链模式的介绍 在开发过程中&#xff0c;我们经常会遇到这样的问题&#xff1a;一个请求需要经过多个对象的处理&#xff0c;但是我们并不知道具体由哪个对象来处理&#xff0c;或者说&#xff0c;我们希望由接收到请求的对象自己去决定如何处理或者是将请求传递给下一个对…

mysql学习笔记7——索引与联合查询,引擎与字符编码

索引相当于给数据库加了个目录&#xff0c;加入索引可以优化查询速度 添加主键可以 增加索引 添加普通索引&#xff0c;普通索引没有其他约束效果 在mysql中可以将查询出的结果插入新表中 联合查询 在mysql对文件读写中存在两种引擎&#xff0c;innodb与myisam&#xff0c;其中…

【自然语言处理】NLP入门(三):1、正则表达式与Python中的实现(3):字符转义符及进制转换

文章目录 一、前言二、正则表达式与Python中的实现1.字符串构造2. 字符串截取3. 字符串格式化输出4. 字符转义符a. 常用字符转义符续行符换行符制表符双引号单引号反斜杠符号回车符退格符 b. ASCII编码转义字符进制转换2 进制8 进制10 进制16 进制进制转换函数 c. Unicode字符\…

关于淘宝的nodejs镜像网址更新后,前端项目出现的一系列问题解决方案。

问题 npm install&#xff0c;之前是成功的&#xff0c;最近不成功。 原因 之前的npm.taobao.org镜像源已经停用 解决方法 把所有的npm.taobao.org替换成npmmirror.com&#xff0c;这个新的淘宝镜像地址 如果使用nvm(没有忽略)需要修改如下&#xff1a; nvm node_mirror…

文字写作困扰?这6款AI写作助手帮你一键解决

有时候写作的时候我们可能会陷入创作困境&#xff0c;思绪纷乱&#xff0c;难以找到合适的表达方式。在此小编特别为大家推荐一些外非常好用的 AI 写作助手&#xff0c;帮助你克服这些问题。让我们来看看其中的6款软件&#xff1a; 1、爱制作AI写作生成器 爱制作AI主要功能是协…

第12届智能计算与无线光通信国际会议(ICWOC 2024)即将召开!

2024年第12届智能计算与无线光通信国际会议&#xff08;ICWOC 2024&#xff09;将于2024年6月21-23日在中国重庆召开。随着深度学习等人工智能技术的不断进步&#xff0c;以自动化、自治为特征的智能应用预计将激增。本届会议主题为“光通信智能链接”&#xff0c;旨在为相关技…

js script中的defer和async

在HTML中&#xff0c;<script>标签可以使用async和defer两个属性来控制外部JavaScript文件的加载和执行方式。这两个属性的目的是优化页面加载时间&#xff0c;但它们以不同的方式工作。下面是每个属性的具体说明&#xff1a; async属性 当你给<script>标签添加a…

经典思路!人参叶际微生物如何发8分文章?

中国中医科学院中药研究所在《Environmental Microbiome》期刊上(IF7.9)发表了关于叶际真菌微生态网络的文章&#xff0c;该研究通过对ITS测序结果和环境因子测定结果以及皂苷含量测定结果进行生信分析&#xff0c;提出了维持微生态网络的稳定性策略和影响皂苷含量的因素。 期刊…

还在用微信截图吗?这2个免费软件你不能错过

大家好&#xff0c;我是知微&#xff01; 说到截图&#xff0c;大家会想到哪款软件呢&#xff0c;是windows系统自带的截图软件&#xff0c;还是登录微信后按AltA触发截图功能&#xff1f; 很多人平时都在使用微信或者QQ截图&#xff0c;但是这种每次都得联网登录才能使用&am…