当前位置: 首页 > article >正文

c/c++数据类型转换.


author: hjjdebug
date: 2025年 05月 18日 星期日 20:28:52 CST
descrip: c/c++数据类型转换.


文章目录

  • 1. 为什么需要类型转换?
    • 1.1 发生的时机:
    • 1.2 常见的发生转换的类型:
  • 2. c语言的类型转换: (Type) value
    • 2.1 c语言的类型变换是如何实现的? 规则是什么?
  • 3. c++ 的static_cast
  • 4. c++的reinterpret_cast
  • 5. dynymic_cast 的使用.
    • 5.1: 测试代码
    • 5.2 statci_cast 处理父子类对象地址
    • 5.3 动态变换: dynamic_cast 处理父子类对象地址
    • 5.4 为什么指针类型老是变来变去的,是什么类型就是什么类型,不变不好吗?
    • 5.4 为什么要用 dynamic_cast ?

本来数据是什么类型就是什么类型,一般是不需要转换的,
但某些特殊情况下会发生转换.

1. 为什么需要类型转换?

因为类型不匹配,所以要进行类型转换.

1.1 发生的时机:

  1. 当进行赋值和运算时有可能发生数据转换.
  2. 进行函数调用时,有可能会发生数据类型转换.
    有可能是说类型不匹配时,会按照一定规则进行变换,如果不是自定义的规则,
    那就是编译器隐含的规则.

1.2 常见的发生转换的类型:

  1. 整形变成浮点型,浮点型变成整形.
  2. 子类指针退化为父类(上变换)和父类指针变换为子类(下变换)
  3. 自定义的类型变换规则.

2. c语言的类型转换: (Type) value

举例:

$ cat main.cpp
#include <stdio.h>
int main()
{int i = 1;double d = i; // 隐式类型转换printf("i:%d, d:%.2f\n",i,d);int* ptr = &i;long address = (long)ptr; // 显示的强制类型转换printf("ptr:%p, address:%ld\n",ptr,address);return 0;
}

执行:
$ ./Test
i:1, d:1.00
ptr:0x7ffca9a5b0bc, addr:140723154694332,addr:0x7ffca9a5b0bc

2.1 c语言的类型变换是如何实现的? 规则是什么?

4 int i = 1;
0x00005555555546c1 <+23>: movl $0x1,-0x24(%rbp) //把1赋值给变量i
5 double d = i; // 隐式类型转换
0x00005555555546c8 <+30>: mov -0x24(%rbp),%eax //取到数值i
0x00005555555546cb <+33>: cvtsi2sd %eax,%xmm0 //变成浮点数
0x00005555555546cf <+37>: movsd %xmm0,-0x20(%rbp) //保存数值到d变量

7 int* ptr = &i;
0x00005555555546f7 <+77>: lea -0x24(%rbp),%rax //取到i的地址
0x00005555555546fb <+81>: mov %rax,-0x18(%rbp) //把地址保存到ptr变量
8 long address = (long)ptr; // 显示的强制类型转换
0x00005555555546ff <+85>: mov -0x18(%rbp),%rax //从ptr地址中取到地址(解引用的意思)
0x0000555555554703 <+89>: mov %rax,-0x10(%rbp) //把地址保存到address 变量
可见地址类型就天然等于long 类型, 它们数值时完全相等的.

c语言会按照它默认规则进行转换,例如把long 转为 int 它也给转,当正确性你自己保证
c++认为c的强制类型转换(type)value 方式太过强暴, 将之分解为4重转换类型,
static_cast, 静态转换
dynymic_cast, 动态转换
reinterpreted_cast, 再解释转换
const_cast, 常变换.

3. c++ 的static_cast

测试代码:

#include <iostream>
using namespace std;
int main()
{double d = 1.23;int a = static_cast<int>(d);cout << a << endl;int* p = &a;
//    int address = static_cast <int>(p);  //error: invalid static_cast from type ‘int*’ to type ‘int’
//    long address = static_cast <long>(p);  //error: invalid static_cast from type ‘int*’ to type ‘long int’long address = reinterpret_cast <long>(p);  //error: invalid static_cast from type ‘int*’ to type ‘long int’cout << address << endl;return 0;
}

我们看到static_cast 把浮点数到int的变换与c下的转换时完全一致的.
汇编代码如下:
5 double d = 1.23;
=> 0x0000555555554892 <+8>: movsd 0x136(%rip),%xmm0 # 0x5555555549d0
0x000055555555489a <+16>: movsd %xmm0,-0x8(%rbp)

6 int a = static_cast(d);
0x000055555555489f <+21>: movsd -0x8(%rbp),%xmm0
0x00005555555548a4 <+26>: cvttsd2si %xmm0,%eax
0x00005555555548a8 <+30>: mov %eax,-0xc(%rbp)
但它拒绝将整形地址向整形变量转换,也拒绝向long 整形变量转换. 编译会直接给出错误.
可见对于static_cast, 它的转换实现与c下的强制转换是一样的.
但对于高风险的转换,它不干了.

如果你确实需要把指针变成整数怎么办,那你可以用另一个关键字reinterpret_cast, 它的要求
会放宽,允许你转换,不过后果自负喽!, 你自己负责使用时的正确性.

4. c++的reinterpret_cast

从上面的例子可以看出,static_cast 对风险高的转换它不干了,让reinterpret_cast来承担风险. reinterpret_cast 的转换方式跟c下的强制转换是一样的.

5. dynymic_cast 的使用.

其主要是为了完成指针类型的上变换(辈份变大了和下变换辈分变小了)
也可能辈分没有变,但从一个基类指针变到了另一个基类指针.
c++的类和继承关系, 一个形象的理解是一个类就对应一个椭圆,子类继承了父类,那就是一个大椭圆套住了一个小椭圆,
继承了2个基类,那就是套住了2个小椭圆.
static_cast 可以处理这种有继承关系的对象指针的转换.
dynymic_cast 也可以处理这种有继承关系的对象指针的转换. 但它是动态的,支持运行时监测.
完成这种转换是需要类型信息的, 下面举例说明转换是怎样进行的,

5.1: 测试代码

$ cat main.cpp
#include <iostream>
using namespace std;
// 假设有2个基类 Base1和Base2 和一个派生类 Derived,各类型指针转换会是什么?
class Base1
{public:// error: cannot dynamic_cast ‘p’ (of type ‘class Base*’) to type ‘class Derived*’ (source type is not polymorphic)// 必需要有一个虚函数,否则编译错误说类型不具有多态性.virtual void foo() {cout<<"from Base1::foo\n";}
};
class Base2
{public:virtual void bar() {cout<<"from Base2::bar\n";}
};class Derived : public Base1, public Base2
{public:void compose() { cout<< "from Derived:compose\n";}
};
int main()
{Derived * pd = new Derived();// 用基类指针,指向一个派生类对象Base1* p1 = pd;Base2* p2 = pd;//当你看到p1,p2的不同,不要奇怪,这里有隐含指针变换cout<<"p1:"<<p1<<",p2:"<<p2<<",pd:"<<pd<<endl;// 使用 dynamic_cast 将 p1 转换为派生类指针 q, 下变换// 能变换吗? 能,因为p1 本来就是派生类对象的指针.//  如果p1 是用 new Base() 创建出来的, 那就转不成继承类指针了!// 转不成了变换的值是nullptr.// dynamic_cast<Derived *> 可看成是一个编译器生成的内置函数// 变化比较复杂. 有对指针的调整. 需要RTTI 运行时类型信息支持.Derived* q1 = dynamic_cast<Derived*>(p1);cout<<"p1:"<<p1<<",q1:"<<q1<<endl; //p1 和q1 是相等的.Derived* q2 = dynamic_cast<Derived*>(p2);//当你看到转出的q1,q2竟然相等,也不用奇怪,因为它们就是一个对象cout<<"q1:"<<q1<<",q2:"<<q2<<",p1:"<<p1<<",p2"<<p2<<endl;//	甚至从Base1 也能导出Base2指针,都是一个对象,它们是可以互相推导计算的.// 推导计算的法则是根据RTTI信息,计算就是加一个偏移,减一个偏移的事情.// 如果转换成功,q1 不为空,可以调用派生类的成员函数 compose()if (q1){q1->compose();}else{cout << "down convert failed\n";}return 0;
}

5.2 statci_cast 处理父子类对象地址

继承类指针向基类指针的隐含转换.
24 // 用基类指针,指向一个派生类对象
25 Base1* p1 = pd;
0x00000000004008f8 <+49>: mov -0x38(%rbp),%rax
0x00000000004008fc <+53>: mov %rax,-0x30(%rbp) //直接赋值

26 Base2* p2 = pd;
0x0000000000400900 <+57>: cmpq $0x0,-0x38(%rbp) //pd==0? 付给0
0x0000000000400905 <+62>: je 0x400911 <main()+74>
0x0000000000400907 <+64>: mov -0x38(%rbp),%rax
0x000000000040090b <+68>: add $0x8,%rax //把值加上8,付给p2
0x000000000040090f <+72>: jmp 0x400916 <main()+79>
0x0000000000400911 <+74>: mov $0x0,%eax
0x0000000000400916 <+79>: mov %rax,-0x28(%rbp)

36 Derived* q1 = static_cast<Derived*>(p1); //静态变换,也叫编译期变换
0x0000000000400999 <+210>: mov -0x30(%rbp),%rax
0x000000000040099d <+214>: mov %rax,-0x20(%rbp) // p1直接付给了q1

// p2付q2, 它就改一改算法, 你说gcc多聪明啊! 它了解意图.
38 Derived* q2 = static_cast<Derived*>(p2);
0x00000000004009ff <+312>: cmpq $0x0,-0x28(%rbp) // p2==0? 付给0
0x0000000000400a04 <+317>: je 0x400a10 <main()+329>
0x0000000000400a06 <+319>: mov -0x28(%rbp),%rax
0x0000000000400a0a <+323>: sub $0x8,%rax // p2减去8,付给q2
0x0000000000400a0e <+327>: jmp 0x400a15 <main()+334>
0x0000000000400a10 <+329>: mov $0x0,%eax
0x0000000000400a15 <+334>: mov %rax,-0x18(%rbp)

5.3 动态变换: dynamic_cast 处理父子类对象地址

36 Derived* q1 = dynamic_cast<Derived*>(p1);
0x00000000004009e9 <+210>: mov -0x30(%rbp),%rax
0x00000000004009ed <+214>: test %rax,%rax
0x00000000004009f0 <+217>: je 0x400a0f <main()+248> //p1==0? 付给0
0x00000000004009f2 <+219>: mov $0x0,%ecx //第4参数,0,偏移数据
0x00000000004009f7 <+224>: mov $0x601da0,%rdx //第3参数,类型信息
0x00000000004009fe <+231>: mov $0x601de8,%rsi //第2参数,类型信息
0x0000000000400a05 <+238>: mov %rax,%rdi // 第一参数p1
0x0000000000400a08 <+241>: callq 0x400810 __dynamic_cast@plt//调用函数
0x0000000000400a0d <+246>: jmp 0x400a14 <main()+253>
0x0000000000400a0f <+248>: mov $0x0,%eax
0x0000000000400a14 <+253>: mov %rax,-0x20(%rbp) //返回值给q1

38 Derived* q2 = dynamic_cast<Derived*>(p2);
0x0000000000400a76 <+351>: mov -0x28(%rbp),%rax
0x0000000000400a7a <+355>: test %rax,%rax
0x0000000000400a7d <+358>: je 0x400a9c <main()+389>
0x0000000000400a7f <+360>: mov $0x8,%ecx //第4参数,8,偏移数据
0x0000000000400a84 <+365>: mov $0x601da0,%rdx //第3参数,类型信息
0x0000000000400a8b <+372>: mov $0x601dd8,%rsi //第2参数,类型信息
0x0000000000400a92 <+379>: mov %rax,%rdi /// 第一参数p2
0x0000000000400a95 <+382>: callq 0x400810 __dynamic_cast@plt
0x0000000000400a9a <+387>: jmp 0x400aa1 <main()+394>
0x0000000000400a9c <+389>: mov $0x0,%eax
0x0000000000400aa1 <+394>: mov %rax,-0x18(%rbp)//返回值给q2
注意: -0x18(%rbp)与-0x20(%rbp)是相差8个byte 而不是2个byte, 一走神有点犯晕.
刚好存储长整形地址.

5.4 为什么指针类型老是变来变去的,是什么类型就是什么类型,不变不好吗?

不变确实挺好,能不变就不要变.
但是c++的2大要点是继承和多态. 另一大要点是封装这就不说了.
就是例子中一个类继承了2个类,本来你用导出类指针是什么都能访问到的.
但是,如果有一个函数,它要求你传入基类的地址而不是导出类地址,这就需要转换了.
把地址调一调,才能访问到正确的数据.
用基类地址还能访问到继承类的函数(虚函数),这就是多态.

运行结果:
$ ./Test
p1:0x16b6e70,p2:0x16b6e78,pd:0x16b6e70
p1:0x16b6e70,q1:0x16b6e70
q1:0x16b6e70,q2:0x16b6e70,p1:0x16b6e70,p20x16b6e78
from Derived:compose

对运行结果的解释
$ ./Test
//p1和p2是不等的(从一个导出类对象地址转换成的两个基类地址是不等的),
//p1等于pd(其中一个基类地址跟导出类地址相等)
p1:0x16b6e70,p2:0x16b6e78,pd:0x16b6e70
//这是逆变换, 转换出的导出类与基类地址相同,但另一个导出类和基类地址不同
p1:0x16b6e70,q1:0x16b6e70
//2个基类转换出了相同的导出类地址q1,q2, 这说明它们是一个对象
q1:0x16b6e70,q2:0x16b6e70,p1:0x16b6e70,p20x16b6e78
from Derived:compose

5.4 为什么要用 dynamic_cast ?

从上边例子中我们看出, static_cast 直接计算了偏移,很简洁, 而dynamic_cast
还要去调用函数__dynamic_cast@plt 才能得到地址,显然代价更高.
那为什么还要用dynamic_cast, 全部改为static_cast 不好吗?
上边的例子是用不着dynamic_cast, 但是, 这里有但是…

我写了一个函数, 传来的是基类指针, 我不知道它真实身份是那种子类,就需要动态指针变换,由此判定它是什么类型. 这就是运行期判断,

测试代码:

#include <iostream>
using namespace std;
class Base {virtual void foo(){}
};
class Derived1 : public Base
{
};class Derived2 : public Base
{
};void deal_it(Base *b)
{auto d1 = dynamic_cast<Derived1 *>(b);
//	auto d1 = static_cast<Derived1 *>(b);if(d1){// 处理Derived1类型                                                 cout<<"is Derived1 type\n";return;}auto d2 = dynamic_cast<Derived2 *>(b);
//	auto d2 = static_cast<Derived2 *>(b);if(d2){// 处理Derived2类型                                                 cout<<"is Derived2 type\n";return;}
}
int main()
{auto b = new Derived2();deal_it(b);return 0;
}

测试结果:
$ ./Test
is Derived2 type

如果你将dynamic_cast改称static_cast, 那就得不到正确结果了, 因为static_cast 不管三七二十一,把指针加个偏移就返回了.
这样转换的指针不为0,就永远只走第一条了.
至于为什么dynamic_cast 能正确工作, 就不再这里说明了.
自定义的类型变换就不在本博举例了,可参考其它博客.

相关文章:

c/c++数据类型转换.

author: hjjdebug date: 2025年 05月 18日 星期日 20:28:52 CST descrip: c/c数据类型转换. 文章目录 1. 为什么需要类型转换?1.1 发生的时机:1.2 常见的发生转换的类型: 2. c语言的类型转换: (Type) value2.1 c语言的类型变换是如何实现的? 规则是什么? 3. c 的static_cast…...

Django 项目的 models 目录中,__init__.py 文件的作用

在 Django 项目的models/init.py文件中&#xff0c;这些导入语句的主要作用是将各个模型类从不同的模块中导入到models包的命名空间中。这样做有以下几个目的&#xff1a; 简化导入路径 当你需要在项目的其他地方使用这些模型时&#xff0c;可以直接从models包导入&#xff0c…...

实验六:FPGA序列检测器实验

FPGA序列检测器实验(远程实验系统) 文章目录 FPGA序列检测器实验(远程实验系统)一、数字电路基础知识1. 时钟与同步2. 按键消抖原理代码讲解:分频与消抖3. 有限状态机(FSM)设计代码讲解:状态机编码与转移4. 边沿检测与信号同步5. 模块化设计二、实验数字电路整体思想三…...

网络的知识的一些概念

1.什么是局域网&#xff0c;什么是广域网 局域网&#xff08;Local area network&#xff09;也可以称为本地网&#xff0c;内网&#xff0c;局域网有这几个发展经历&#xff1a; 最开始电脑与电之间是直接用网线连接的 再后来有了集线器&#xff08;&#xff09; 再后来出…...

芋道项目,商城模块数据表结构

一、需求 最近公司有新的业务需求&#xff0c;调研了一下&#xff0c;决定使用芋道&#xff08;yudao-cloud&#xff09;框架,于是从github&#xff08;https://github.com/YunaiV/yudao-cloud&#xff09;上克隆项目&#xff0c;选用的是jdk17版本的。根据项目启动手册&#…...

yarn任务筛选spark任务,判断内存/CPU使用超过限制任务

yarn任务筛选spark任务&#xff0c;判断内存/CPU使用超过限制任务 curl -s “http://it-cdh-node01:8088/ws/v1/cluster/apps?statesRUNNING” | jq ‘.apps.app | map(select(.applicationType “SPARK” ) | select(.allocatedMB > 102400 or .allocatedVCores > 50)…...

【氮化镓】HfO2钝化优化GaN 器件性能

2025年,南洋理工大学的Pradip Dalapati等人在《Applied Surface Science》期刊发表了题为《Role of ex-situ HfO2 passivation to improve device performance and suppress X-ray-induced degradation characteristics of in-situ Si3N4/AlN/GaN MIS-HEMTs》的文章。该研究基…...

c#的内存指针操作(仅用于记录)

c#也可以直接操作内存指针&#xff0c;如下为示例&#xff1a; unsafe {byte[] a {1,2,3};fixed (byte* p1 a, p2 &a[^1]){Debugger.Log(1, "test", $"max index:{p2-p1}");Debugger.Log(1, "test", $"address:{(long)p1:X}")…...

常见机器学习算法简介:回归、分类与聚类

机器学习说到底&#xff0c;不就三件事&#xff1a; 预测一个数 —— 回归 判断归属哪个类 —— 分类 自动把数据分组 —— 聚类 别背术语&#xff0c;别管定义&#xff0c;先看问题怎么解决。 一、回归&#xff08;Regression&#xff09; 干嘛的&#xff1f; 模型输出一…...

SpringBoot项目里面发起http请求的几种方法

在Spring Boot项目中发起HTTP请求的方法 在Spring Boot项目中&#xff0c;有几种常用的方式可以发起HTTP请求&#xff0c;以下是主要的几种方法&#xff1a; 1. 使用RestTemplate (Spring 5之前的主流方式) // 需要先注入RestTemplate Autowired private RestTemplate restT…...

Linux下Nginx源码安装步骤详解

以下是在Linux系统下从源码安装Nginx的详细步骤及解释&#xff1a; 1. 下载Nginx源码 步骤&#xff1a; wget http://nginx.org/download/nginx-1.25.3.tar.gz tar -zxvf nginx-1.25.3.tar.gz cd nginx-1.25.3解释&#xff1a; wget&#xff1a;从官网下载Nginx源码包&#…...

SQLMesh 增量模型从入门到精通:5步实现高效数据处理

本文深入解析 SQLMesh 中的增量时间范围模型&#xff0c;介绍其核心原理、配置方法及高级特性。通过实际案例说明如何利用该模型提升数据加载效率&#xff0c;降低计算资源消耗&#xff0c;并提供配置示例与最佳实践建议&#xff0c;帮助读者在实际项目中有效应用这一强大功能。…...

Zookeeper 入门(二)

4. Zookeeper 的 ACL 权限控制( Access Control List ) Zookeeper 的ACL 权限控制,可以控制节点的读写操作,保证数据的安全性&#xff0c;Zookeeper ACL 权 限设置分为 3 部分组成&#xff0c;分别是&#xff1a;权限模式&#xff08;Scheme&#xff09;、授权对象&#xff08…...

【架构篇】安全架构-双向认证

mTLS&#xff08;Mutual TLS&#xff09;详解&#xff1a;双向认证的原理、流程与实践 摘要 mTLS&#xff08;Mutual TLS&#xff09;是一种基于数字证书的双向身份验证协议&#xff0c;广泛应用于微服务通信、金融交易等高安全场景。本文深入解析mTLS的工作原理、认证流程、W…...

负载均衡—会话保持技术详解

一、会话保持的定义 会话保持&#xff08;Session Persistence&#xff09;是一种负载均衡策略&#xff0c;其核心机制是确保来自同一客户端的连续请求&#xff0c;在特定周期内被定向到同一台后端服务器进行处理。这种机制通过记录和识别客户端的特定标识信息&#xff0c;打破…...

Flask快速入门和问答项目源码

Flask基础入门 源码&#xff1a; gitee&#xff1a;我爱白米饭/Flask问答项目 - 码云 目录 1.安装环境2.【debug、host、port】3.【路由params和query】4.【模板】5.【静态文件】6.【数据库连接】6.1.安装模块6.2.创建数据库并测试连接6.3.创建数据表6.4.ORM增删改查 6.5.ORM模…...

go语法大赏

前些日子单机房稳定性下降&#xff0c;找了好一会才找到真正的原因。这里面涉及到不少go语法细节&#xff0c;正好大家一起看一下。 一、仿真代码 这是仿真之后的代码 package mainimport ("fmt""go.uber.org/atomic""time" )type StopSignal…...

软件工程各种图总结

目录 1.数据流图 2.N-S盒图 3.程序流程图 4.UML图 UML用例图 UML状态图 UML时序图 5.E-R图 首先要先了解整个软件生命周期&#xff1a; 通常包含以下五个阶段&#xff1a;需求分析-》设计-》编码 -》测试-》运行和维护。 软件工程中应用到的图全部有&#xff1a;系统…...

R-tree详解

R-tree 是一种高效的多维空间索引数据结构&#xff0c;专为快速检索空间对象&#xff08;如点、线、区域&#xff09;而设计。它广泛应用于地理信息系统&#xff08;GIS&#xff09;、计算机图形学、数据库等领域&#xff0c;支持范围查询、最近邻搜索等操作。以下是其核心原理…...

AAAI2024 | 基于特征多样性对抗扰动攻击 Transformer 模型

Attacking Transformers with Feature Diversity Adversarial Perturbation 摘要-Abstract引言-Introduction相关工作-Related Work方法-Methodology实验-Experiments结论-Conclusion 论文链接 本文 “Attacking Transformers with Feature Diversity Adversarial Perturbatio…...

关于数据湖和数据仓的一些概念

一、前言 随着各行业数字化发展的深化,数据资产和数据价值已越来越被深入企业重要发展的战略重心,海量数据已成为多数企业生产实际面临的重要问题,无论存储容量还是成本,可靠性都成为考验企业数据治理的考验。本文来看下海量数据存储的数据湖和数据仓,数据仓库和数据湖,…...

鸿蒙OSUniApp制作自定义的下拉菜单组件(鸿蒙系统适配版)#三方框架 #Uniapp

UniApp制作自定义的下拉菜单组件&#xff08;鸿蒙系统适配版&#xff09; 前言 在移动应用开发中&#xff0c;下拉菜单是一个常见且实用的交互组件&#xff0c;它能在有限的屏幕空间内展示更多的选项。虽然各种UI框架都提供了下拉菜单组件&#xff0c;但在一些特定场景下&…...

C++面试2——C与C++的关系

C与C++的关系及核心区别的解析 一、哲学与编程范式:代码组织的革命 过程式 vs 多范式混合 C语言是过程式编程的典范,以算法流程为中心,强调“怎么做”(How)。例如,实现链表操作需手动管理节点指针和内存。 C++则是多范式语言,支持面向对象(OOP)、泛型编程(模板)、函…...

常用的Java工具库

1. Collections 首先是 java.util 包下的 Collections 类。这个类主要用于操作集合&#xff0c;我个人非常喜欢使用它。以下是一些常用功能&#xff1a; 1.1 排序 在工作中&#xff0c;经常需要对集合进行排序。让我们看看如何使用 Collections 工具实现升序和降序排列&…...

基于LabVIEW的双音多频系统设计

目录 1 系统设计概述 双音多频(Dual-Tone Multi-Frequency, DTMF)信号是一种广泛应用于电话系统中的音频信号,通过不同的频率组合表示不同的按键。每个按键对应两个频率,一个低频和一个高频,共同组成独特的信号。在虚拟仪器技术快速发展的背景下,利用LabVIEW等图形化编程…...

R S的EMI接收机面板

图片摘自R & S官网。 根据您提供的第一张图&#xff08;设备前面板带屏幕的图像&#xff09;&#xff0c;这是 Rohde & Schwarz ESRP7 EMI Test Receiver 的正面显示界面&#xff0c;我将对屏幕上显示的参数逐项进行解读&#xff1a; &#x1f5a5;️ 屏幕参数解读 左…...

[ctfshow web入门] web122

信息收集 这一题把HOME开放了&#xff0c;把#和PWD给过滤了 <?php error_reporting(0); highlight_file(__FILE__); if(isset($_POST[code])){$code$_POST[code];if(!preg_match(/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|US…...

Nginx+Lua 实战避坑:从模块加载失败到版本冲突的深度剖析

Nginx 集成 Lua (通常通过 ngx_http_lua_module 或 OpenResty) 为我们提供了在 Web 服务器层面实现动态逻辑的强大能力。然而,在享受其高性能和灵活性的同时,配置和使用过程中也常常会遇到各种令人头疼的问题。本文将结合实际案例,深入分析在 Nginx+Lua 环境中常见的技术问题…...

LangChain框架-Chain 链详解

摘要 本文基于源码分析与官方文档梳理&#xff0c;系统解析 LangChain 框架中的核心组件 Chain 链&#xff0c;旨在帮助开发者深入理解其设计原理、功能分类及实践应用场景。 作为 LangChain 的核心机制&#xff0c;Chain 链采用管道-过滤器&#xff08;Pipe-Filter&#xff09…...

Java虚拟机 - JVM与Java体系结构

Java虚拟机 JVM与Java体系结构为什么要学习JVMJava与JVM简介Java 语言的核心特性JVM&#xff1a;Java 生态的基石JVM的架构模型基于栈的指令集架构&#xff08;Stack-Based&#xff09;基于寄存器的指令集架构&#xff08;Register-Based&#xff09;JVM生命周期 总结 JVM与Jav…...