详解C++中的ANSI、Unicode和UTF8三种字符编码及相互转换

news2024/11/28 22:34:22

目录

1、概述

2、Visual Studio中的字符编码

3、ANSI窄字节编码

4、Unicode宽字节编码

5、UTF8编码

6、如何使用字符编码

7、三种字符编码之间的相互转换(附源码)

8、Windows系统对使用ANSI窄字节字符编码的程序的兼容

9、字符编码导致程序启动失败的案例 


       在C++编程中,我们有时需要去处理字符串编码的相关问题,常见的字符编码有ANSI窄字节编码、Unicode宽字节编码及UTF8可变长编码。很多人在处理字符串编码问题时都会有疑惑,即便是有多年工作经验的朋友也可能搞不清楚。所以有必要讲一下这三种字符编码以及如何去使用它们。

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

1、概述

       在日常的软件开发过程中,会时不时地去处理不同编码格式的字符串,特别是在处理文件路径的相关场景中,比如我们要通过路径去读写文件、通过路径去加载库文件等。常见的字符编码格式有ANSI窄字节编码、Unicode宽字节编码以及UTF8可变长编码。在Linux系统中,主要使用UTF8编码;在Windows系统中,既支持ANSI编码,也支持Unicode编码。

       通用的大小写字母和数字则使用全球统一的固定编码,即ASCII码。

       ANSI编码是各个国家不同语种下的字符编码,其字符的编码值只在该语种中有效,不是全球统一编码的,比如中文的GB2312编码就是简体中文的ANSI编码。

       Unicode编码则是全球统一的双字节编码,所有语种的字符在一起统一的编码,每个字符的编码都是全球唯一的。

       UTF8编码是一种可变长的宽字节编码,也是一种全球统一的字符编码。

       本文将以WIndows中使用Visual Studio进行C++编程时需要处理的字符编码问题为切入点,详细讲解一下字符编码的相关内容。

       至于各个字符编码之间转换接口的源码,可以查看我之前写的文章:

VC++中ANSI、UNICODE与UTF-8字符编码之间的转换(附源码)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/123589349

2、Visual Studio中的字符编码

       在Visual Studio中编写C++代码时,该如何指定字符串的编码呢?其实很简单,使用双引号括住的字符串,使用的就是ANSI窄字节编码;使用L+双引号括住的字符串,使用的就是Unicode宽字节编码,如下所示:

char* pStr = "This is a Test.";    // ANSI编码
WCHAR* pWStr = L"This is a Test."; // Unicode宽字节编码

我们也可以使用_T宏定义来指定字符串的编码格式:

TCHAR* pStr = _T("This is a Test.");

设置_T后,则由工程配置属性中的字符集设置来确定到底是使用哪种编码:

如果选择多字节字符集,_T就被解释为双引号,即使用ANSI窄字节编码;如果选择Unicode字符集,_T就被解释为L,即使用Unicode宽字节编码。

      其实,如果在工程配置中选择使用Unicode字符集,工程中会添加一个_UNICODE宏,如下所示:

如果选择多字节字符集,则没有_UNICODE宏。代码中正是通过这个宏来判定到底使用哪种编码的,比如对_T的判断:

#ifdef  _UNICODE
#define  _T(X)    L(X)
#else
#define  _T(X)    (X)
#endif  // _UNICODE

        和字符编码相对应的,Windows系统提供两个版本的API,比如给窗口设置文字的API函数,一个是支持ANSI窄字节编码的SetWindowTextA(ANSI窄字节版本),一个是支持Unicode宽字节编码的SetWindowTextW(Wide宽字节版本)。我们也可以直接调用SetWindowText,然后由_UNICODE宏判断到底使用哪个版本,如下:

#ifdef _UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif // !UNICODE

3、ANSI窄字节编码

        ANSI编码是不同语种下的字符编码,比如GB2312字符编码就是简体中文的本地编码。

ANSI编码是个本地范畴,只适用于对应的语种,每个字符的编码不是全球唯一的编码,只在对应的语种中有效。对于中文GB2312编码的字符串,如果当成英文的ANSI编码来解析,则结果会是乱码!

       但是对于大小写英文字母和数字的ANSI编码,是字符ASCII码,英文字母和数字的ACSII码是全球统一的,比如大写字母A的ASCII码是65(十六进制是41H),数字0的ASCII码是48(十六进制是30H)。所以在所有语种中,大小写字母及数字的ANSI编码,都是能识别的。不同语种下的本地文字字符,一般是不能相互识别的。

       使用中文ANSI编码的字符串开发的程序(代码中使用的都是中文字符串,使用的是ANSI窄字节编码),拿到俄文操作系统中可能显示的都是乱码,因为在俄文的ANSI编码中只识别俄文的ANSI编码出来的字符串,无法识别中文ANSI编码的字符串。这里主要有两类字符乱码问题,一是UI界面上显示的文字是乱码;二是使用路径去创建文件或访问文件时会因为路径中的字符是乱码,导致文件创建或访问失败。

4、Unicode宽字节编码

       Unicode编码是全球统一的字符编码,每个语种下的每个字符的编码值都是全球唯一的,即在Unicode编码集中可以识别每个语种下的所有字符。所以为了实现软件对多语种(多国语言)的支持,我们在开发软件时要选择Unicode字符编码,使用Unicode编码的字符串,调用Unicode版本的API。

       系统在提供包含字符串参数的API时,都会提供两个版本,一个是ANSI版本的,一个是Unicode版本的,主要体现在对字符串编码的处理上,比如SetWindowTextA(ANSI版本)和SetWindowTextW(Wide宽字节Unicode版本)。我们可以直接调用W版本API,但一般我们调用API时,我们不指定调用哪个版本,是通过设置工程属性中的编码格式来确定使用哪个版本:

#ifdef _UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif // !UNICODE

具体情况已在上面的“Visual Studio中的字符编码”章节中详细讲述,此处不再赘述。

        在Unicode编码中,每个字符都占两个字节。对于大小写字母和数字,当他们出现在字符串中时,对应的内存中存放的是它们的ASCII码值,只占一个字节,在Unicode 2字节编码中,高位将填充0。

5、UTF8编码

       UTF8编码是可变长字符编码格式,是一种紧凑型存储的编码格式,也是一种宽字节的、全球统一的编码格式。UTF8编码中的所有字符,包括不同语种下面的字符,都是全球唯一编码的,在所有的系统都能识别出来。

       UTF8编码中,能用一个字节存放的,就用一个字节存放,比如大小写字母和数字,在字符串中存放的ASCII码,只需要一个字节去存放就够了。所以在UTF8编码中,大小写字母和数字只占一个字节。我们常用的中文字符,一个字符则占用3个字节。

UTF8编码之所以称之为可变长的,是因为其根据字符需要的实际存储空间大小来编码的,比如大小写字母和数字的存储只需要1个字节就够了,所以它们只占一个字节,而一个中文字符则占三个字节。

6、如何使用字符编码

       Windows系统主要使用Unicode编码,Linux则使用UTF8编码,后台服务器一般使用的都是Linux系统,而客户端是运行在Windows操作系统上的。一般客户端与服务器交互的数据的字符串编码统一使用全球统一编码的UTF8编码。

       客户端收到UTF8编码的字符串后,需要将UTF8字符换转换后显示在界面上。如果客户端使用的是Unicode编码字符集,将UTF8编码的字符串转换成Unicode编码的字符串后再显示到界面上;如果客户端使用的是多字节ANSI编码,则需要再将Unicode编码的字符串转成ANSI编码的字符串。

这里注意一下,UTF8编码的字符串要转成ANSI编码的,不能直接将UTF8转成ANSI,需要先将UTF8转成Unicode,然后再将Unicode转成ANSI。

      为了实现软件对多语种(多国语言)的支持,我们在开发Windows软件时要选择Unicode字符编码,使用Unicode编码的字符串,调用Unicode版本的API。

       此外,对于一些开源的项目,提供的API接口中有字符串参数的,一般都明确指定字符串编码为UTF8。因为一般情况下开源库都支持跨平台,既支持Windows平台,也支持Linux平台,所以要选择使用通用的、大家都是识别的UTF8编码。

      比如在轻便型数据库sqlite开源库中,用于打开数据库文件的接口sqlite3_open,就明确指定使用UTF8编码的字符串:

**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
** query components of a URI. A hexadecimal escape sequence consists of a
** percent sign - "%" - followed by exactly two hexadecimal digits 
** specifying an octet value. ^Before the path or query components of a
** URI filename are interpreted, they are encoded using UTF-8 and all 
** hexadecimal escape sequences replaced by a single byte containing the
** corresponding octet. If this process generates an invalid UTF-8 encoding,
** the results are undefined.
**
** <b>Note to Windows users:</b>  The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
** codepage is currently defined.  Filenames containing international
** characters must be converted to UTF-8 prior to passing them into
** sqlite3_open() or sqlite3_open_v2().
**
** <b>Note to Windows Runtime users:</b>  The temporary directory must be set
** prior to calling sqlite3_open() or sqlite3_open_v2().  Otherwise, various
** features that require the use of temporary files may fail.
**
** See also: [sqlite3_temp_directory]
*/
SQLITE_API int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
SQLITE_API int sqlite3_open16(
  const void *filename,   /* Database filename (UTF-16) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
SQLITE_API int sqlite3_open_v2(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb,         /* OUT: SQLite db handle */
  int flags,              /* Flags */
  const char *zVfs        /* Name of VFS module to use */
);

对于使用Unicode编码的Windows程序,代码中使用的都是Unicode编码的字符串,在调用sqlite3_open接口之前,需要将Unicode编码的字符串转成UTF8编码的。如果收到开源库中回调上来的UTF8编码的字符串数据,则需要将UTF8编码的字符串转成Unicode后,才能显示到UI界面上,才能使用转码后的Unicode字符串去调用Windows系统API。


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到430多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2: 

C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域的多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!

专栏3:  

C++常用软件分析工具从入门到精通案例集锦汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++软件辅助分析工具有PE工具、Dependency Walker、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!

专栏4:   

VC++常用功能开发汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。

专栏5: 

开源组件及数据库技术icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html

以多年的开发实战为基础,分享一些开源组件及数据库技术!


7、三种字符编码之间的相互转换(附源码)

      有朋友曾经提出这样的疑问,是不是我在Windows下把一个双引号括起来的ANSI窄字节字符串赋值给WCHAR宽字节的指针:

WCHAR* pStr = "测试字符串";

字符串就能自动转换成Unicode宽字节?答案是否定的,这样的赋值操作并不会做字符编码转换,右侧的仅仅是字符串的首地址,作为地址,可以赋值给很多数据类型,比如int、void*、char*等等。

       那可能有人会说,那为啥我在Unicode下,将一个ANSI编码的字符串传给MFC库中的CString类对象时会自动转换成Unicode宽字符呢?这和上面的情况不一样的,是因为CString类重载了赋值操作符函数,在函数内部做了字符编码的转换,代码如下:

const CUIString& CUIString::operator=(LPCSTR lpsz)
{
	int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
	AllocBeforeWrite(nSrcLen);
	_ANSIToUnicode(m_pchData, lpsz, nSrcLen+1);
	ReleaseBuffer();
	return *this;
}

       一般情况下,是需要我们自己去编写字符编码转换的代码的。下面来看一下,我们在进行Windows C++编程时,需要调用哪些API接口实现上述三种编码之间的转换。

       字符编码相互转换的源代码请查看链接:VC++中ANSI、UNICODE与UTF-8字符编码之间的转换(附源码)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/123589349

8、Windows系统对使用ANSI窄字节字符编码的程序的兼容

       现在的Windows程序基本都用Unicode字符编码了,工程属性中将字符集都设置成了Unicode字符集,代码中都使用Unicode编码的字符串。但是还有一些老的程序使用的还是ANSI窄字节的字符。那这些老的程序如何才能在外文的操作系统中正常运行呢?微软提供了一种兼容这些老程序的办法。

       可以到Windows控制面板的区域语言设置中将非Unicode语言设置成程序中使用的字符语种即可,相关设置的操作步骤截图如下:

在上图中选择程序中字符使用的语种即可。

       下面我们来看看使用ANSI编码的程序放到外文操作系统中运行为什么会出现乱码。假设将某程序中使用的是中文ANSI窄字节编码的字符串,放到英文操作系统中运行,默认情况下,UI界面上会显示乱码。至于为什么会显示乱码,是因为英文操作系统中默认情况下设置的非Unicode语言是英语(美国):

这个非Unicode语言设置直接影响我们调用MultiByteToWideChar和WideCharToMultiByte接口中的CP_ACP标记对应的本地ANSI字符集编码库。在上面界面中如果将非Unicode语言设置成英语(美国),则使用英文的ANSI字符编码库;如果设置成中文简体,则使用中文简体的ANSI字符集编码库。

       程序中调用API函数SetWindowTextA给程序中的窗口设置文字或标题时,传入的字符串是ANSI窄字节编码的,而SetWindowTextA函数内部及底层的流程中会使用本地设置的ANSI字符集编码库将ANSI编码的字符串转成Unicode编码的字符串后再设置到窗口中,最终界面上看到的文字是Unicode编码的文字。所以在将中文字符转换成Unicode时,如果使用的是本地设置的英文字符集编码进行转换,则会出现乱码;如果使用中文简体的字符集编码进行转换,则能正常显示。

       所以,要让使用中文ANSI编码字符的程序能在英文操作系统中正常显示并运行,需要将英文操作系统中区域语言设置项中的“非Unicode程序的语言”设置成中文才行。

9、字符编码导致程序启动失败的案例 

       几天前正好排查了一例因为字符编码导致的程序启动失败的实例,在这里简单的说一下。客户将软件安装到一个包含中文字符的路径中,点击启动软件没反应,软件始终启动不了,也没有弹出什么报错的提示框。客户于是向我们反馈了这个问题。

       我们使用向日葵远程到客户的机器上,经对比发现,如果我们将软件安装到默认的C:\Program Files(X86)的英文路径下,程序是能正常启动的,所以我们初步怀疑可能是字符编码引起的问题。重新将软件安装到D盘包含中文字符的路径后,我们用windbg启动软件,刚启动windbg中就检测到看异常,异常发生在加载主程序依赖库的过程中。

启动软件的exe主程序时,会将该exe依赖的所有库依次加载到进程空间中,待所有的库都加载起来后,才会将exe主程序模块启动起来,才能看到软件的主界面。

如果在加载库时产生了异常,整个启动过程将被终止,软件也就无法启动了。

       异常发生在加载音视频编解码库mediaproc.dll中,于是在windbg中输入kn命令,查看异常时的函数调用堆栈(事先已经取来了pdb符号文件)。调用堆栈显示时崩溃在mediaproc.dll库的DllMain函数中,加载dll库时都会调用到该接口。

       根据调用堆栈中显示的代码行号,到编解码库的源代码中查看,发现是崩溃在一个函数接口指针的调用上,有可能是遇到空指针了。一般情况下,使用windbg实时调试时是能看到函数中的局部变量及类对象内存中的值,但这次有点特殊,看不到内存中的值。

       于是和负责维护音视频编解码库的同事沟通了一下, 编解码库mediaproc.dll在DllMain中会使用绝对路径(当前exe主程序的路径)去调用LoadLibrary去动态加载更底层的库,然后调用GetProcAddress把底层库的接口都拿出来保存到指针变量中。编解码库mediaproc.dll是调用ANSI版本的API函数GetModuleFileNameA获取exe主程序的路径,问题就出在这个函数的调用上,这个函数获取的路径中包含乱码。

      D盘包含中文字符的文件夹在系统中是能正常显示的,为啥获取的路径中会包含乱码呢?于是查看了客户Windows操作系统版本,是Windows10 IOT版本,经常见到旗舰版、专业版和教育版,这个IOT版本还是第一次遇到!于是又去查看控制面板区域语言中的非Unicode语言选项设置:

系统中设置的非Unicode语言为英语(美国),这样系统指向的本地ANSI字符编码库就是英语(美国)的ANSI字符编码库。

       D盘中包含中文字符的文件夹在系统中能正常显示的,为啥调用GetModuleFileNameA获取到的路径中会有乱码呢?系统中显示的中文字符是Unicode编码的,当我们调用ANSI版本的GetModuleFileNameA获取路径时,GetModuleFileNameA函数内部会将Unicode编码的字符串转成ANSI编码的,转换时使用的是系统指向的本地ANSI字符编码库,也就是英语(美国)的ANSI字符编码库,而英语(美国)的ANSI字符编码库根本不识别中文字符,所以出现了乱码!

       GetModuleFileNameA返回的路径中包含乱码,导致LoadLibrary失败,导致GetProcAddress返回NULL值,从而导致call这个NULL地址产生了异常!

       对于当前出问题的编解码库,需要修改一下代码,需要调用Unicode版本的接口。目前临时的解决办法有两个:

1)将软件安装在英文路径中;

2)在控制面板的区域语言中将非Unicode语言改成简体中文。

       我们的软件已经声称做到了对多语种的支持,虽然UI层已经支持Unicode了,但底层的库因为是不同开发团队开发维护的,需要再逐一排查一下了!

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

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

相关文章

1-8 C语言分支循环语句

C语言的语句分为 5 类 1&#xff1a;表达式语句2&#xff1a;函数调用语句3&#xff1a;控制语句4&#xff1a;复合语句5&#xff1a;空语句 控制语句&#xff1a;用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式&#xff0c;它们由特定的语句定义符组成&#x…

【日记】遇到了一个 “不愿睁眼看世界也没受过社会毒打” 的逆天群友(464 字)

正文 今天坐在柜台玩了一天手机…… 手机都玩没电了快。下午在劝一个群友睁眼看世界&#xff0c;实在劝不动。他真的太逆天了&#xff0c;我不清楚这么高学历的人&#xff0c;怎么能说出这么天真的话。逆天又离谱。 晚上的时间几乎全在做家务。平时晚上都是跳舞来着&#xff0c…

云原生架构案例分析_1.某旅行公司云原生改造

随着云计算的普及与云原生的广泛应用&#xff0c;越来越多的从业者、决策者清晰地认识到“云原生化将成为企业技术创新的关键要素&#xff0c;也是完成企业数字化转型的最短路径”。因此&#xff0c;具有前瞻思维的互联网企业从应用诞生之初就扎根于云端&#xff0c;谨慎稳重的…

git推送代码到github拒绝推送的解决方案

这里描述一下本地推送的场景&#xff0c;首先我在码云上建立了一个前端项目&#xff0c;进行了自己的个性化开发&#xff0c;后期在github上创建了一个一样的项目仓库存放代码。使用webstorm进行代码开发。在下面这个位置可以选择推送的代码位置。 选择推送github仓库之后&…

图文详解Windows系统下搭建mysql开发环境——mysql Community 8 和 navicat Premium 17 的安装和使用

在正式开始学习使用MySQL之前&#xff0c;我们有必要先搭建一个良好的开发环境&#xff0c;让我们的学习和工作效率事半功倍。 本文涉及到的软件百度云盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1jj_YajEv8adeEjMrXLhOTQ?pwd1023 提取码&#xff1a;1023 目录 …

React的表单学习

react的表单的双向绑定 // userState实现计数实例 import {useState} from react// 1.声明一个react的状态 -useState// 2.核心绑定流程//1.通过value属性绑定react状态//2.绑定onChange事件&#xff0c;通过事件参数e拿到输入框最新的值&#xff0c;反向修改到react状态 func…

Linux--标准IO库

一、标准IO简介 所谓标准 I/O 库则是标准 C 库中用于文件 I/O 操作&#xff08;譬如读文件、写文件等&#xff09;相关的一系列库函数的集合&#xff0c;通常标准 I/O 库函数相关的函数定义都在头文件 <stdio.h> 中&#xff0c;所以我们需要在程序源码中包含 <s…

[office] excel工作表数据分级显示 #其他#笔记

excel工作表数据分级显示 如下图1所示的工作表数据&#xff0c;我们按东区、西区、南区、北区来建立分级显示。 图1 这里先利用“创建组”命令建立分级显示。选取单元格区域A3:E5&#xff0c;单击功能区“数据”选项卡“分级显示”组中的“创建组——创建组…”命令&#xff…

使用Cython编译Python源码加密加速,有这一篇就够了!

0 前言 python是一门脚本语言&#xff0c;运行时由python虚拟机解释执行。当我们使用python设计好算法给第三方使用时只能提供源码&#xff0c;任何运行我们算法的人都可以看到源码以及对应的算法思路。因此&#xff0c;需要一定手动保护源码。 最简单的保护方式是使用代码混…

对待谷歌百度等搜索引擎的正确方式

对待百度、谷歌等搜索引擎的方式是&#xff0c;你要站在搜索引擎之上&#xff0c;保持自己的独立思想和意见。 当谷歌宣布他们将会根据一个名为“Alphabet”的新控股公司来进行业务调整时&#xff0c;在科技界引起了一片恐慌之声。 永远不要说这是一个公司一直在做的事情。不…

【Linux】深入解析动静态库:原理、制作、使用与动态链接机制

文章目录 前言&#xff1a;1. 什么是动静态库2. 动静态库的制作和使用3. 动态库的查找问题4. 理解动态库的加载4.1. 站在系统的角度理解4.2. 编址、可执行程序4.3. 动态库动态链接和加载问题 总结&#xff1a; 前言&#xff1a; 在软件开发中&#xff0c;动静态库是两种重要的…

【栈】1106. 解析布尔表达式

本文涉及知识点 栈 LeetCode 1106. 解析布尔表达式 布尔表达式 是计算结果不是 true 就是 false 的表达式。有效的表达式需遵循以下约定&#xff1a; ‘t’&#xff0c;运算结果为 true ‘f’&#xff0c;运算结果为 false ‘!(subExpr)’&#xff0c;运算过程为对内部表达式…

2024年【R2移动式压力容器充装】考试技巧及R2移动式压力容器充装复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 R2移动式压力容器充装考试技巧参考答案及R2移动式压力容器充装考试试题解析是安全生产模拟考试一点通题库老师及R2移动式压力容器充装操作证已考过的学员汇总&#xff0c;相对有效帮助R2移动式压力容器充装复审考试学…

ubuntu系统 kubeadm方式搭建k8s集群

服务器环境与要求&#xff1a; 三台服务器 k8s-master01 192.168.26.130 操作系统&#xff1a; Ubuntu20.04 k8s-woker01 192.168.26.140 操作系统&#xff1a; Ubuntu20.04 k8s-woker02 192.168.26.150 操作系统&#xff1a; Ubuntu20.04 最低配置&#xff1a;2…

【启程Golang之旅】协程和管道操作

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

【ARM Cache 与 MMU 系列文章 7.6 -- ARMv8 MMU 配置 寄存器使用介绍】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 MMU 转换控制寄存器 TCR_ELxTCR_ELx 概览TCR_ELx 寄存器字段详解TCR 使用示例Normal MemoryCacheableShareability MMU 内存属性寄存器 MAIR_ELxMAIR_ELx 寄存器结构内存属性字段Devic…

人工智能在【肿瘤生物标志物】领域的最新研究进展|顶刊速递·24-06-08

小罗碎碎念 本期文献速递的主题是——人工智能在“肿瘤生物标志物”领域的最新研究进展。 重点关注 今天推荐的6篇文献中&#xff0c;第二篇和第三篇是小罗最喜欢的&#xff0c;因为对于临床来说&#xff0c;比较具有实际意义&#xff0c;也和自己的想法很契合。 尤其是第三篇…

华安保险:核心系统分布式升级,提升保费规模处理能力2-3倍 | OceanBase企业案例

在3月20日的2024 OceanBase数据库城市行的活动中&#xff0c;安保险信息科技部总经理王在平发表了以“保险行业核心业务系统分布式架构实践”为主题的演讲。本文为该演讲的精彩回顾。 早在2019年&#xff0c;华安保险便开始与OceanBase接触&#xff0c;并着手进行数据库的升级…

uniapp自定义的下面导航

uniapp自定义的下面导航 看看效果图片吧 文章目录 uniapp自定义的下面导航 看看效果图片吧 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6aa0e964741d4dd3a58f4e86c4bf3247.png) 前言一、写组件、我这里就没有写组件了直接写了一个页面&#xff1f;总结 前言 在…

ubuntu使用docker安装openwrt

系统&#xff1a;ubuntu24.04 架构&#xff1a;x86 1. 安装docker 1.1 离线安装 docker下载地址 根据系统版本&#xff0c;依次下载最新的三个关于docker的软件包 container.io&#xff08;注意后缀版本顺序&#xff09;docker-ce-clidocker-ce 然后再ubuntu系统中依次按顺…