28 C 语言作用域详解:作用域特性(全局、局部、块级)、应用场景、注意事项

1 作用域简介

        作用域定义了代码中标识符(如变量、常量、数组、函数等)的可见性与可访问范围,即标识符在程序的哪些位置能够被引用或访问。在 C 语言中,作用域主要分为三类:

  • 全局作用域
  • 局部作用域
  • 块级作用域

        需注意,同一作用域内不允许声明同名的标识符


2 全局作用域

        在函数和代码块(如分支语句、循环语句)之外定义的变量、常量、数组等具有全局作用域,可在程序的任何位置访问,通常称为全局变量、全局常量、全局数组

2.1 全局常量的特性

  1. 定义方式:
    1. 在函数体外用 const 修饰的变量为全局常量。
    2. 用 #define 定义的宏标识符通常被视为全局常量(但严格来说是预处理文本替换)。
  2. 作用域:
    • 默认全局可见,其他文件可通过 extern 声明使用(后续章节讲解)
    • 必须显式初始化,未初始化的全局常量会导致编译错误
  3. 不可修改性:全局常量在程序运行期间不可修改,试图修改会导致编译错误
#include <stdio.h>const double PI = 3.14; // 全局常量// 计算圆的面积
void printCircleArea(double radius)
{printf("半径为%.2f的圆面积=%.2f\n", radius, PI * radius * radius);
}// 主函数
int main()
{printCircleArea(2.0); // 输出: 半径为2.00的圆面积=12.56return 0;
}

        程序在 VS Code 中的运行结果如下所示:

2.2 全局变量的特性

  1. 生命周期:程序运行期间始终存在
  2. 默认初始化:
    • 若未显式初始化,全局变量会自动初始化为零值(如 int 为 0,double 为 0.0)
    • 字符类型默认初始化为空字符 \0
#include <stdio.h>// 全局变量未显式初始化
int a;    // 自动初始化为 0
double b; // 自动初始化为 0.0
char c;   // 自动初始化为 '\0'int main()
{printf("a=%d\n", a); // 输出: a=0printf("b=%f\n", b); // 输出: b=0.000000printf("c=%c\n", c); // 输出: c= (空字符)return 0;
}

        程序在 VS Code 中的运行结果如下所示:

2.3 全局数组的特性

  1. 默认初始化:未初始化的全局数组元素自动清零(数值类型为 0,字符类型为 \0)
  2. 访问范围:可在所有函数中直接使用
#include <stdio.h>int arr[5];  // 所有元素自动初始化为 0
char msg[6]; // 所有元素自动初始化为 '\0'int main()
{// 计算数组的长度int length = sizeof(arr) / sizeof(arr[0]);// 遍历数组 arrfor (int i = 0; i < length; i++){printf("%d ", arr[i]); // 输出: 0 0 0 0 0}printf("\n");printf("字符数组:%s\n", msg); // 输出: 字符数组: (空字符串)return 0;
}

        程序在 VS Code 中的运行结果如下所示:

2.4 全局函数的特性

  1.  定义方式:在函数体外定义的函数默认为全局函数。
  2. 作用域:
    1. 默认全局可见,其他文件可通过函数声明调用
    2. 使用 static 修饰的函数仅在当前文件内可见(限制作用域,后续章节讲解)
  3. 无嵌套定义:C 语言不支持函数嵌套定义,所有函数必须定义在全局作用域。
#include <stdio.h>// 全局函数
void greet()
{printf("Hello from global function!\n");
}int main()
{greet(); // 调用全局函数return 0;
}

        程序在 VS Code 中的运行结果如下所示:

2.5 全局作用域示例

#include <stdio.h>// 1. 全局常量(整个程序可见)
const double TAX_RATE = 0.1; // 税率// 2. 全局变量(整个程序可见)
double totalIncome = 0.0; // 总收入
int callCount = 0;        // 函数调用计数器// 3. 全局函数(整个程序可见)
void calculateTax(double income)
{callCount++; // 修改全局变量,调用一次增加一次totalIncome += income;double tax = income * TAX_RATE;printf("收入=%.2f, 税额=%.2f\n", income, tax);
}// 4. 静态全局函数(仅当前文件可见)
static void printSummary()
{printf("总收入=%.2f\n", totalIncome);printf("函数调用次数=%d\n", callCount);
}// 5. 另一个全局函数
void resetSystem()
{totalIncome = 0.0; // 重置全局变量callCount = 0;     // 重置全局变量printf("系统已重置\n");
}int main()
{// 调用全局函数calculateTax(1000.0);calculateTax(2000.0);// 调用静态全局函数(仅在当前文件可见)printSummary();// 调用另一个全局函数,重置数据resetSystem();// 再次调用全局函数calculateTax(500.0);// 再次打印摘要printSummary();return 0;
}

        程序在 VS Code 中的运行结果如下所示:

2.6 注意事项

  1. 避免滥用全局变量
    • 问题:全局变量易被意外修改,导致代码耦合度高、难以维护
    • 建议:优先使用局部变量或函数参数传递数据,仅在必要时使用全局变量(如跨模块共享状态)
  2. 谨慎修改全局状态
    • 问题:全局变量的修改可能影响多个函数,尤其在多线程环境中易引发竞争条件(Race Condition)
    • 建议:减少全局变量的可写性(如用 const 修饰只读数据),或通过封装接口操作数据
  3. 限制全局函数的作用域
    • 问题默认全局函数可能与其他文件同名函数冲突(链接时重复定义)
    • 建议:若函数仅在当前文件使用,用 static 修饰限制其作用域,避免命名冲突
  4. 避免全局常量的硬编码
    • 问题:全局常量直接嵌入代码中,修改配置需重新编译
    • 建议:将全局常量集中定义在头文件中(如 #define 或 const),便于统一维护
  5. 注意全局成员的命名规范
    • 问题:全局变量/函数命名冲突可能导致难以调试的错误
    • 建议:为全局成员添加统一前缀(如 g_ 或 k_),例如 g_globalVar、k_MAX_USERS
  6. 警惕全局变量的生命周期
    • 问题:全局变量在程序启动时初始化,退出时销毁,可能占用资源过久
    • 建议:若变量仅在特定阶段使用,考虑使用局部变量或动态分配内存(malloc/free)

3 局部作用域

3.1 局部作用域的定义

  • 定义:在函数内定义的变量、常量、数组等具有局部作用域,仅在定义它们的函数内部可见
  • 别名:局部变量、局部常量、局部数组等。
  • 形参的局部性:函数的形参也是局部变量,仅在函数内有效

3.2 局部作用域示例

#include <stdio.h>void add(int a)
{// 局部变量int b = 20;// 局部常量const double PI = 3.14;// 局部数组int nums[] = {10, 20, 30};printf("(a + b + nums[0]) * PI = %f\n", (a + b + nums[0]) * PI);
}int main()
{// 调用函数add(100); // 输出:(a + b + nums[0]) * PI = 103 * 3.14 = 408.200000// 在 add 函数外使用局部变量、局部常量和局部数组是非法的// printf("%d\n", b);       // 错误:b 未定义// printf("%f\n", PI);      // 错误:PI 未定义// printf("%d\n", nums[0]); // 错误:nums 未定义return 0;
}

        程序在 VS Code 中的运行结果如下所示:

3.3 局部作用域的优先级

        若局部作用域中定义了与全局作用域同名的标识符,优先使用局部定义(就近原则)

#include <stdio.h>// 全局变量
int a = 100;
int b = 200;void add()
{// 若局部作用域中定义了与全局作用域同名的标识符,优先使用局部定义int a = 300; // 局部变量,覆盖全局变量 aa += 10;     // 修改局部变量 ab += 10;     // 修改全局变量 bprintf("函数 add 内部:a = %d, b = %d\n", a, b);
}int main()
{add();          // 输出:函数 add 内部:a = 310, b = 210printf("函数 add 外部:a = %d, b = %d\n", a, b); // 输出:a = 100, b = 210return 0;
}

        程序在 VS Code 中的运行结果如下所示:

3.4 局部变量和数组的初始化

  • 未初始化的风险:局部变量和数组若未显式初始化,其值为未定义的垃圾值(系统之前分配的内存残留值),可能导致程序行为异常

  • 强烈建议:始终显式初始化局部变量和数组。

#include <stdio.h>int main()
{// 示例 1:未初始化的局部变量int uninitialized_var; // 未初始化,值为垃圾值printf("未初始化的变量 uninitialized_var: %d\n", uninitialized_var);// 示例 2:未初始化的局部数组int uninitialized_arr[5]; // 未初始化,数组元素值为垃圾值printf("未初始化的数组 uninitialized_arr: ");for (int i = 0; i < 5; i++){printf("%d ", uninitialized_arr[i]);}printf("\n");// 示例 3:显式初始化的局部变量int initialized_var = 0; // 显式初始化为 0printf("显式初始化的变量 initialized_var: %d\n", initialized_var);// 示例 4:显式初始化的局部数组int initialized_arr[5] = {0}; // 显式初始化为全 0printf("显式初始化的数组 initialized_arr: ");for (int i = 0; i < 5; i++){printf("%d ", initialized_arr[i]);}printf("\n");return 0;
}

        程序在 VS Code 中的运行结果如下所示:

3.5 注意事项

  1. 变量覆盖问题
    1. 现象:在局部作用域中定义与全局变量或外部局部变量同名的变量时,会覆盖同名变量(仅在当前作用域内生效),可能导致逻辑混淆或错误
    2. 建议:
      • 避免在局部作用域中定义与全局变量同名的变量
      • 若需区分,可为局部变量添加独特命名前缀(如 local_)或后缀(如 _local)
  2. 生命周期限制

    1. 现象:局部变量在函数调用时创建,函数返回时销毁。若在函数外访问局部变量的地址或引用,会导致未定义行为(如内存错误或程序崩溃)

    2. 建议:不要返回局部变量的地址或引用
  3. 初始化依赖
    1. 现象:局部变量若未初始化,其值是未定义的(可能是随机内存值),导致不可预测的行为
    2. 建议:始终初始化局部变量,对于指针,可初始化为 NULL

4 块级作用域

4.1 块级作用域的定义

  • 定义:块级作用域是 C99 标准引入的特性,指在代码块(如 {} 包裹的分支语句、循环语句等)中定义的变量、常量、数组等,仅在该代码块内部可见
  • 别名:块级变量、块级常量、块级数组等,也可统称为局部变量、局部常量、局部数组。
  • 特性:与函数内的局部变量一致,块级作用域的变量在代码块外不可访问。

4.2 块级作用域示例

#include <stdio.h>int main()
{// 示例 1:代码块中的块级作用域{// 块级变量int a = 20;// 块级常量const double PI = 3.14;printf("a * PI = %f\n", a * PI); // 输出:a * PI = 62.800000}// 示例 2:分支语句中的块级作用域if (1){// 块级数组int nums[] = {10, 20, 30};printf("%d %d %d\n", nums[0], nums[1], nums[2]); // 输出:10 20 30}// 示例 3:循环语句中的块级作用域for (int i = 0; i < 5; i++){printf("%d ", i); // 输出:0 1 2 3 4}// 以下代码会报错,因为变量已超出块级作用域// printf("%d\n", a);       // 报错:'a' undeclared// printf("%f\n", PI);      // 报错:'PI' undeclared// printf("%d\n", nums[0]); // 报错:'nums' undeclared// printf("%d\n", i);       // 报错:'i' undeclaredreturn 0;
}

        程序在 VS Code 中的运行结果如下所示:

4.3 块级作用域的优先级

        块级作用域的优先级遵循就近原则(也称为词法作用域或静态作用域)。具体规则如下:

  1. 变量查找顺序:
    • 当访问一个变量时,编译器会从当前代码块开始查找。
    • 如果当前代码块中未找到该变量,则逐层向外查找(父代码块、全局作用域等)
    • 若在所有作用域中均未找到变量,则编译报错(变量未定义)。
  2. 变量覆盖:
    • 内层代码块的变量会覆盖外层同名的变量(仅在当前代码块内生效)
    • 退出内层代码块后,外层变量的值会恢复。
#include <stdio.h>int globalVar = 100; // 全局变量int main()
{int outerVar = 10; // 外层局部变量if (1){int outerVar = 20;                         // 覆盖外层 outerVar(仅在 if 块内生效)printf("if 块内 outerVar=%d\n", outerVar); // 输出:20{int outerVar = 30;                            // 覆盖 if 块的 outerVar(仅在内部代码块生效)printf("内部代码块 outerVar=%d\n", outerVar); // 输出:30}printf("if 块恢复 outerVar=%d\n", outerVar); // 输出:20}printf("外层 outerVar=%d\n", outerVar);   // 输出:10printf("全局 globalVar=%d\n", globalVar); // 输出:100return 0;
}

        程序在 VS Code 中的运行结果如下所示:

4.4 块级作用域的优势 

  1. 避免命名冲突:块级变量仅在有限范围内可见,减少全局命名冲突的风险
  2. 资源管理:块级变量的生命周期与代码块绑定,便于管理内存和资源
  3. 代码可读性:明确变量的作用范围,提高代码可读性和可维护性。

4.5 注意事项

  1. 变量生命周期限制
    1. 现象:块级作用域中的变量在进入代码块时创建,退出代码块时销毁。若在代码块外访问,会导致未定义行为(如编译错误或随机值)
    2. 建议:
      • 不要在代码块外访问块级变量
      • 若需跨代码块共享数据,可在外部作用域定义变量
  2. 变量覆盖问题
    1. 现象:块级作用域中定义的变量会覆盖同名的外部变量(仅在当前块内生效),可能导致逻辑混淆
    2. 建议:
      • 避免在块级作用域中定义与外部变量同名的变量
      • 若需区分,可为块级变量添加独特命名前缀(如 block_)
  3.  C99 之前的限制
    1. 现象:在 C99 之前(如 C89),for 循环的变量必须声明在循环外,导致变量作用域过大
    2. 建议:
      • 使用 C99 或更高版本,利用块级作用域限制变量范围
      • 若使用旧标准,手动限制变量作用域(如通过额外代码块)

5 作用域对比总结表

特性全局作用域局部作用域块级作用域
定义位置函数或代码块外部函数或代码块内部任意代码块 {} 内部(如 if、for、while)
生命周期程序启动时创建,退出时销毁函数调用时创建,返回时销毁进入代码块时创建,退出代码块时销毁
可见性整个程序(所有文件)仅在定义它的函数或代码块内仅在定义它的代码块内
默认值默认初始化为 0 或 NULL无默认值(未初始化时为随机值)无默认值(未初始化时为随机值)
变量覆盖风险高(易被意外修改,命名冲突)中(仅在函数内冲突)中(仅在代码块内冲突)
内存分配位置通常为数据段(静态存储区)栈内存栈内存
适用场景跨模块共享状态(如配置、常量)函数内部临时数据限制变量作用域(如 for 循环、if 条件)
潜在问题耦合度高、难以维护、线程安全问题栈溢出(大数组)、变量逃逸(返回地址)嵌套过深、栈溢出(大数组)

6 作用域思考题

6.1 思考题 1

        请仔细阅读以下代码,分析程序的运行结果。

#include <stdio.h>double price = 200.0;void test01()
{printf("test01: %.2f \n", price);
}void test02()
{price = 250.0;printf("test02: %.2f \n", price);
}int main()
{printf("main price=%.2f \n", price);test01();test02();test01();return 0;
}
  • 运行结果分析:
    • 初始时,全局变量 price = 200.0。
    • main 打印全局变量 price = 200.00。
    • test01() 打印全局变量 price = 200.00(未修改)。
    • test02() 修改全局变量 price = 250.0,并打印 price = 250.00。
    • test01() 再次打印全局变量 price = 250.00(因 test02 已修改)。

        程序在 VS Code 中的运行结果如下所示:

6.2 思考题 2

        请仔细阅读以下代码,分析程序的运行结果。

#include <stdio.h>int n = 10;void func1()
{int n = 20;printf("func1 n: %d\n", n);
}void func2(int n)
{printf("func2 n: %d\n", n);
}void func3()
{printf("func3 n: %d\n", n);
}int main()
{int n = 30;printf("main n:%d\n", n);func1();func2(n);func3();{int n = 40;printf("block n: %d\n", n);}return 0;
}
  • 运行结果分析:
    • 初始时,全局变量 n = 10,但被 main 的局部变量遮蔽,实际输出 n = 30。
    • func1() 打印其局部变量 n = 20(遮蔽全局变量)。
    • func2(n) 打印 main 传递的实参 n = 30(形参作用域遮蔽全局变量)。
    • func3() 无局部变量 n,因此访问全局变量 n = 10。
    • 代码块中的 n = 40 仅在块内有效,退出后恢复为 main 的局部变量 n = 30(但此时已无后续操作)。

        程序在 VS Code 中的运行结果如下所示:

6.3 思考题 3

        请仔细阅读以下代码,分析程序的运行结果。

#include <stdio.h>int x = 5;void funcA()
{int x = 10;printf("funcA: %d\n", x);{int x = 15;printf("funcA block: %d\n", x);}printf("funcA end: %d\n", x);
}void funcB(int x)
{printf("funcB: %d\n", x);x += 5;printf("funcB modified: %d\n", x);
}void funcC()
{printf("funcC: %d\n", x);
}int main()
{int x = 20;printf("main: %d\n", x);funcA();funcB(x);funcC();{int x = 30;printf("main block: %d\n", x);}printf("main end: %d\n", x);return 0;
}
  • 运行结果分析:
    • ​​​​​​​初始时,全局变量 x = 5,但被 main 的局部变量遮蔽。
    • main 打印局部变量 x = 20。
    • funcA() 定义局部变量 x = 10,打印 10;代码块内定义 x = 15,打印 15;退出代码块后恢复为 10,打印 10。
    • funcB(x) 接收 main 的局部变量 x = 20,打印 20;修改形参 x += 5 后打印 25(不影响全局或 main 的 x)。
    • funcC() 无局部变量 x,访问全局变量 x = 5(未被修改)。
    • main 的代码块定义 x = 30,打印 30;退出后恢复为 main 的局部变量 x = 20,打印 20。

        程序在 VS Code 中的运行结果如下所示:

提示:VS Code 变量作用域快速判断技巧

        在 VS Code 中调试或阅读代码时,若需快速判断变量是全局还是局部变量,可按以下步骤操作:

  1. 定位变量定义
    • 将鼠标悬停在目标变量名上
    • 按住 Ctrl(Windows/Linux) 或 Cmd(Mac) 键,同时单击鼠标左键
  2. 确认变量类型
    • 若跳转至函数或代码块外部(如文件开头),则为全局变量。
    • 若跳转至函数内部或代码块内,则为局部变量。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat运行比较卡顿进行参数调优

在Tomcat conf/catalina.bat或catalina.sh中 的最上面增加参数 1. 初步调整参数&#xff08;缓解问题&#xff09; set JAVA_OPTS -Xms6g -Xmx6g -Xmn3g # 增大新生代&#xff0c;减少对象过早晋升到老年代 -XX:MetaspaceSize256m -XX:MaxMetaspaceS…

WSL2 安装与Docker安装

注意&#xff1a;如没有科学上网请勿尝试&#xff0c;无法判断是否会因网络错误导致的安装失败&#xff01;&#xff01;&#xff01; WSL2&#xff08;Windows Subsystem for Linux 2&#xff09; 功能简介&#xff1a; WSL2 是微软提供的在 Windows 上运行完整 Linux 内核的…

Redis的安装与使用

网址&#xff1a;Spring Data Redis 安装包&#xff1a;Releases tporadowski/redis GitHub 解压后 在安装目录中打开cmd 打开服务&#xff08;注意&#xff1a;每次客户端连接都有先打开服务&#xff01;&#xff01;&#xff01;&#xff09; 按ctrlC退出服务 客户端连接…

springboot-响应接收与ioc容器控制反转、Di依赖注入

1.想将服务器中的数据返回给客户端&#xff0c;需要在controller类上加注解&#xff1a;ResponseBody; 这个注解其实在前面已经使用过&#xff0c;RestController其实就包含两个注解&#xff1a; Controller ResponseBody 返回值如果是实体对象/集合&#xff0c;将会转换为j…

将材质球中的纹理属性对应的贴图保存至本地

通过Texture2D的EncodeToPNG方法将纹理转为图片形式 material.GetTexture方法通过属性名获取纹理贴图 material.SetTexture方法通过属性名设置纹理贴图 属性名可在shader代码中查看 using UnityEngine; using System.IO;public class TextureSaver : MonoBehaviour {public…

MySQL半同步复制配置和参数详解

目录 1 成功配置主从复制 2 加载插件 3 半同步复制监控 4 半同步复制参数 1 成功配置主从复制 操作步骤参考&#xff1a;https://blog.csdn.net/zyb378747350/article/details/148309545 2 加载插件 #主库上 MySQL 8.0.26 之前版本: mysql>INSTALL PLUGIN rpl_semi_syn…

【笔记】Windows 成功部署 Suna 开源的通用人工智能代理项目部署日志

#工作记录 本地部署运行截图 kortix-ai/suna&#xff1a; Suna - 开源通用 AI 代理 项目概述 Suna 是一个完全开源的 AI 助手&#xff0c;通过自然对话帮助用户轻松完成研究、数据分析等日常任务。它结合了强大的功能和直观的界面&#xff0c;能够理解用户需求并提供结果。其强…

PCB制作入门

文章目录 1 嘉立创使用旋转 2元器件选择MP2315SLM7815与LM7915 1 嘉立创使用 旋转 空格旋转 2元器件选择 MP2315S MP2315S 是一款内置功率 MOSFET 的高效率同步整流降压开关变换器。 其输入电压范围为 4.5V 至 24V &#xff0c;能实现 3A 连续输出电流&#xff0c;负载与…

2025——》NumPy中的np.logspace使用/在什么场景下适合使用np.logspace?NumPy中的np.logspace用法详解

1.NumPy中的np.logspace使用: 在 NumPy 中,np.logspace函数用于生成对数尺度上等间距分布的数值序列,适用于科学计算、数据可视化等需要对数间隔数据的场景。以下是其核心用法和关键细节: 一、基础语法与参数解析: numpy.logspace(start, stop, num=50, endpoint=True, ba…

Java实现中文姓名转拼音生成用户信息并写入文件

中文姓名转拼音 Java实现中文姓名转拼音生成用户信息并写入文件&#xff08;shili域名版&#xff09;一、项目背景与功能简介二、技术栈与核心组件2.1 主要技术2.2 功能模块 三、核心代码解析3.1 主函数逻辑&#xff08;流程控制&#xff09;3.2 拼音转换模块&#xff08;核心功…

Google car key:安全、便捷的汽车解锁新选择

有了兼容的汽车和 Android 手机&#xff0c;Google car key可让您将Android 手机用作车钥匙。您可以通过兼容的 Android 手机锁定、解锁、启动汽车并执行更多功能。但是&#xff0c;Google car key安全吗&#xff1f;它是如何工作的&#xff1f;如果我的手机电池没电了怎么办&a…

如何轻松将 iPhone 备份到外部硬盘

当您的iPhone和电脑上的存储空间有限时&#xff0c;您可能希望将iPhone备份到外部硬盘上&#xff0c;这样可以快速释放iPhone上的存储空间&#xff0c;而不占用电脑上的空间&#xff0c;并为您的数据提供额外的安全性。此外&#xff0c;我们还提供 4 种有效的解决方案&#xff…

AI炼丹日志-22 - MCP 自动操作 Figma+Cursor 自动设计原型

MCP 基本介绍 官方地址&#xff1a; https://modelcontextprotocol.io/introduction “MCP 是一种开放协议&#xff0c;旨在标准化应用程序向大型语言模型&#xff08;LLM&#xff09;提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…

机器学习-线性回归基础

一、什么是回归 依据输入x写出一个目标值y的计算方程&#xff0c;求回归系数的过程就叫回归。简言之&#xff1a;根据题意列出方程&#xff0c;求出系数的过程就叫做回归。 回归的目的是预测数值型的目标值y&#xff0c;分类的目的预测标称型的目标值y。 二、线性回归 2.1线性…

解决RAGFlow(v0.19.0)有部分PDF无法解析成功的问题。

ragflow版本为&#xff1a;v0.19.0 1.解析的时候报错&#xff1a;Internal server error while chunking: Coordinate lower is less than upper。 看报错怀疑是分片的问题&#xff0c;于是把文档的切片方法中的“建议文本块大小”数值&#xff08;默认512&#xff09;调小&…

【前端】html2pdf实现用前端下载pdf

npm安装完后&#xff0c;编写代码。 <template><div id"pdf-content">需要被捕获为pdf的内容</div> </template><script> import html2pdf from html2pdf.js;export default {methods: {downloadPdf() {const element document.getE…

从零实现富文本编辑器#4-浏览器选区模型的核心交互策略

先前我们提到了&#xff0c;数据模型的设计是编辑器的基础模块&#xff0c;其直接影响了选区模块的表示。选区模块的设计同样是编辑器的基础部分&#xff0c;编辑器应用变更时操作范围的表达&#xff0c;就需要基于选区模型来实现&#xff0c;也就是说选区代表的意义是编辑器需…

数论——质数和合数及求质数

质数、合数和质数筛 质数和合数及求质数试除法判断质数Eratosthenes筛选法&#xff08;埃氏筛&#xff09;线性筛&#xff08;欧拉筛&#xff09; 质数有关OJ列举P1835 素数密度 - 洛谷简单的哥赫巴德猜想和cin优化 质数和合数及求质数 一个大于 1 的自然数&#xff0c;除了 1…

多商户系统源码性能调优实战:从瓶颈定位到高并发架构设计!

在电商业务爆发式增长的今天&#xff0c;多商户系统作为支撑平台方、入驻商家和终端消费者的核心枢纽&#xff0c;其性能表现直接决定了商业变现效率。当你的商城在促销期间崩溃&#xff0c;损失的不仅是订单&#xff0c;更是用户信任。 本文将深入剖析多商户系统源码性能优化的…

JDBC连不上mysql:Unable to load authentication plugin ‘caching_sha2_password‘.

最近为一个spring-boot项目下了mysql-9.3.0&#xff0c;结果因为mysql版本太新一直报错连不上。 错误如下&#xff1a; 2025-06-01 16:19:43.516 ERROR 22088 --- [http-nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispat…