devc++源文件未编译_iOS 编译知识小结

  • 简介
  • 源码到可执行文件流程
  • 编译器
  • 编译流程
    • 预处理(preprocessor)
    • 词法分析(lexical anaysis)
    • 语法分析(semantic analysis)
    • CodeGen
    • 生成汇编代码
    • 生成目标文件
    • 生成可执行文件
  • Xcode中查看Clang编译.m文件信息
  • Xcode常见编译报错分析
    • 1. duplicate symbols报错
    • 2. symbol(s) not found for architecture x86_64/arm64
  • 应用场景
    • Clang Attributes
    • Clang警告处理
    • 预处理
    • Clang插件开发
  • 总结

简介

拖更很久了,今天水文一篇。简单介绍下iOS底层编译的相关知识,帮助我们充分理解了iOS编译的过程,相信会对我们后续的开发有一定帮助。

源码到可执行文件流程

首先看一下iOS代码是如何从源码变成可执行文件的,有助于我们了解程序从编译到运行的全流程

  1. 编译器Clang会将源码XXX.m编译为目标文件XXX.o
  2. 链接器会将目标文件链接打包进最终的可执行文件Mach-O中
  3. 点击App ICON时,动态链接器dyld会加载可执行文件以及依赖的动态库,并最终执行到main.m里,至此App启动完成

f1e9861642fbfe8e555c3c4329ac980f.png

编译器

编译器是将编程语言转换为目标语言的程序,大多数编译器由两部分组成:前端和后端。

  • 前端负责词法分析,语法分析,生成中间代码;
  • 后端以中间代码作为输入,进行行架构无关的代码优化,接着针对不同架构生成不同的机器码。

前后端依赖统一格式的中间代码(IR),使得前后端可以独立的变化。新增一门语言只需要修改前端,而新增一个CPU架构只需要修改后端即可。

Objective C/C/C++使用的编译器前端是clang,swift是swift,后端都是LLVM。

5d51a9900fb872f1a5deabe2f1921539.png

LLVM是一个模块化和可重用的编译器和工具链技术的集合,Clang 是 LLVM 的子项目,是 C,C++ 和 Objective-C 编译器,目的是提供惊人的快速编译,比 GCC 快3倍,

LLVM 还可以提供一种代码编写良好的中间表示 IR,这意味着它可以作为多种语言的后端,这样就能够提供语言无关的优化同时还能够方便的针对多种 CPU 的代码生成。

编译流程

Objective-C的编译器前端是Clang,诞生之初是为了替代GCC,提供更快的编译速度。我们可以通过下面这张图来了解Clang编译的大致流程:

<br> (二维码自动识别)

下面我们通过clang命令来具体分析下源码编译的流程:

首先在命令行里输入

clang -ccc-print-phases main.m

可以看到源文件编译需要的几个不同的阶段

➜  clang -ccc-print-phases main.m
0: input, "main.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output  //预编译
2: compiler, {1}, ir  //编译成中间代码ir
3: backend, {2}, assembler  //生成汇编
4: assembler, {3}, object  //生成目标文件.O
5: linker, {4}, image  //链接成可执行文件
6: bind-arch, "x86_64", {5}, image

接下来我们新建一个main.m并详细来看下每个步骤分别做了什么

main.m
#include <stdio.h>int main() {printf("hello worldn");return 0;
}

预处理(preprocessor)

我们用下面的命令来查看clang预处理的结果:

clang -E main.m
注:如果main.m中用到了UIKit等类,可以在命令后添加-sysroot参数,记得将sdk换成你本机的版本,后续命令解决方法相同。如下所示:
clang -E main.m -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk

可以看到预处理后的文件行数有很多,在最后可以找到main函数

# 13 "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/ShareSheet.h" 2 3
# 17 "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIKit.h" 2 3
# 10 "main.m" 2
# 1 "./AppDelegate.h" 1
# 11 "./AppDelegate.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *window;@end
# 11 "main.m" 2int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, ((void *)0), NSStringFromClass([AppDelegate class]));}
}

预处理会替进行头文件引入(递归操作),宏替换#define,注释处理,条件编译(#ifdef),#pargma处理等操作。比如#include "stdio.h"就是告诉预处理器将这一行替换成头文件stdio.h中的内容,这个过程是递归的:因为stdio.h也有可能包含其头文件。

词法分析(lexical anaysis)

预处理完成后就会进行词法分析,这里会把代码切成一个个 Token,比如大小括号,等于号还有字符串等。

clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m

语法分析(semantic analysis)

语法分析会校验语法的正确性,然后将所有的节点组成抽象语法树AST。有了抽象语法树,clang就可以对这个树进行分析,找出代码中的错误。比如类型不匹配,亦或Objective C中向target发送了一个未实现的消息。

业内对Clang自定义插件或者开发静态检测插件都是基于AST语法树来分析。相关知识后续会学到。AST是开发者编写clang插件主要交互的数据结构,clang也提供很多API去读取AST。更多细节:Introduction to the Clang AST。
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

在输出里可以看到相关的AST结果,如下图:

050e880a54e7fc3473eda3777cd49af1.png

CodeGen

CodeGen 会负责将语法树自顶向下遍历逐步翻译成 LLVM IR,IR 是编译过程的前端的输出,也是后端的输入。
Objective C代码也在这一步会进行runtime的桥接:property合成,ARC处理等。

clang -S -fobjc-arc -emit-llvm main.m -o main.ll

查看main.ll的内容如下:

...
; Function Attrs: noinline optnone ssp uwtable
define i32 @main(i32, i8**) #0 {%3 = alloca i32, align 4%4 = alloca i32, align 4%5 = alloca i8**, align 8store i32 0, i32* %3, align 4store i32 %0, i32* %4, align 4store i8** %1, i8*** %5, align 8%6 = call i8* @llvm.objc.autoreleasePoolPush() #1%7 = load i32, i32* %4, align 4%8 = load i8**, i8*** %5, align 8%9 = load %struct._class_t*, %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_", align 8%10 = bitcast %struct._class_t* %9 to i8*%11 = call i8* @objc_opt_class(i8* %10)%12 = call %0* @NSStringFromClass(i8* %11)%13 = bitcast %0* %12 to i8*%14 = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %13) #1%15 = bitcast i8* %14 to %0*%16 = call i32 @UIApplicationMain(i32 %7, i8** %8, %0* null, %0* %15)store i32 %16, i32* %3, align 4%17 = bitcast %0* %15 to i8*call void @llvm.objc.release(i8* %17) #1, !clang.imprecise_release !10call void @llvm.objc.autoreleasePoolPop(i8* %6)%18 = load i32, i32* %3, align 4ret i32 %18
}; Function Attrs: nounwind
...

如果在项目配置中开启了 bitcode, 苹果还会做进一步的优化,有新的后端架构还是可以用这份优化过的 bitcode 去生成。

clang -emit-llvm -c main.m -o main.bc

生成汇编代码

clang -S -fobjc-arc main.m -o main.s

生成目标文件

汇编器以汇编代码作为输入,将汇编代码转换为机器代码,最后输出目标文件(object file)

clang -fmodules -c main.m -o main.o

接下来我们用nm命令,查看下main.o中的符号

➜  BuildTest nm -nm main.o(undefined) external _printf
0000000000000000 (__TEXT,__text) external _main

这里可以看到_printf是一个是undefined external的。undefined表示在当前文件暂时找不到符号_printf,而external表示这个符号是外部可以访问的,对应表示文件私有的符号是non-external。

生成可执行文件

链接器可以把编译产生的.o文件和(dylib,a,tbd)文件,生成一个mach-o文件

clang main.o -o main

接着在命令行执行./main,可以看到输出了结果:hello world。
最后我们用nm命令来分析下可执行文件的符号表:

➜  BuildTest nm -nm main(undefined) external _printf (from libSystem)(undefined) external dyld_stub_binder (from libSystem)
0000000100000000 (__TEXT,__text) [referenced dynamically] external __mh_execute_header
0000000100000f60 (__TEXT,__text) external _main
0000000100002008 (__DATA,__data) non-external __dyld_private

可以看到_printf仍然是undefined,但是后面多了一些信息:from libSystem,表示这个符号来自于libSystem,会在运行时动态绑定。

以上就是Clang编译源文件的完整流程了。

Xcode中查看Clang编译.m文件信息

如果你想在 Xcode 中查看,可以通过 Show the report navigator 里对应 target 的 build 中查看每个 .m 文件的 clang 编译信息,如下图:

e056a439bfc4daf1c806ee2477c4b07d.png

随便找一个.m文件编译信息,可以看到Xcode会首先对任务进行描述:

CompileC /Users/chenaibin/Library/Developer/Xcode/DerivedData/PodIntegrationDemo-achbuytjuwbatqbzvlwflifarxwa/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/podLibB.build/Objects-normal/x86_64/podClsB.o /Users/chenaibin/Work/DiDi/iOSDemo/BuildErrorDemo/podLibB/Classes/podClsB.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler (in target 'podLibB' from project 'Pods')

接下来对会更新工作路径,同时设置 PATH

cd /Users/chenaibin/Work/DiDi/iOSDemo/BuildErrorDemo/PodIntegrationDemo/Pods
export LANG=en_US.US-ASCII
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"

接下来就是实际的编译命令

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -target x86_64-apple-ios9.0-simulator -fmessage-length=0 -fobjc-arc… -Wno-missing-field-initializers ... -DDEBUG=1 ... -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk -iquote ... -I... -F...-c /.../podClsB.m -o /.../podClsB.o

clang 用到的命令参数如下:

-x 编译语言比如objective-c
-arch 编译的架构,比如arm64
-f 以-f开头的。
-W 以-W开头的,可以通过这些定制编译警告
-D 以-D开头的,指的是预编译宏,通过这些宏可以实现条件编译
-iPhoneSimulator13.0.sdk 编译采用的iOS SDK版本
-I 把编译信息写入指定的辅助文件
-F 需要的Framework
-c 标识符指明需要运行预处理器,语法分析,类型检查,LLVM生成优化以及汇编代码生成.o文件
-o 编译结果

Xcode常见编译报错分析

1. duplicate symbols报错

第一个常见的编译报错原因就是duplicate symbols,如下图就是因为我们链接后的可执行文件存在了重复的类导致的。

db7d6ffa9c20d070e67fd17fe2814fe3.png

注:由于我们工程是由CocoaPods构建的,在xcconfig中OTHER_LINK_FLAG都会被默认设置成$(inherited) -ObjC ......,这会导致工程配置里Other Linker Flags会带上 -ObjC标记,如果我们手动删除了-ObjC,就会发现在编译时不会有duplicate symbols的错误了。但是运行的时候可能会出现unrecognized selector sent to class XXX的错误,这是由于静态库中的分类并没被链接器链接进可执行文件中。

-ObjC会把静态库中所有的类和分类都链接进可执行文件,所以会出现duplicate symbols的错误。下面是官方描述:

This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes.

2. symbol(s) not found for architecture x86_64/arm64

第二个常见报错是在某个架构下找不到相关符号,这是因为引用的某个静态库并没有包含当前工程制式下的架构类型,解决方案是将静态库.a文件合并x86_64/arm64等架构为fat file,再集成到工程里使用。

报错原因如下图:

c0fe4033998ea4a4616d30b012a5abcf.png
提示:遇到这种情况时,有时候多次pod update也不能解决报错原因。这是因为你本地缓存了有问题的静态库文件,可在以下目录下找到相关类库并删除,再执行pod install下载fix后的静态库文件。CocoaPods官方缓存目录:~/Library/Caches/CocoaPods/Pods

这个错误还有另外一种情况,当同一个pod在多个不同的端集成时可能会遇到。报错信息大致如下:

258728a37547a05be4dca316778222b0.png

问题原因:在ProjectA中集成了podA和podB,podA使用了#if __has_include("podB中的cls.h")集成了podB中的类;当切换到ProjectB时,只会依赖podA一个库,这个时候编译就会上图中的错误。

解决方案:在ProjectB中将podA以源码重新编译一遍即可。

应用场景

Clang Attributes

在平时开发中,我们经常会遇到头文件里有__attribute__的用法,它是一个高级的的编译器指令,它允许开发者指定更更多的编译检查和一些高级的编译期优化。

__attribute__ 语法格式为:__attribute__ ((attribute-list)) 放在声明分号“;”前面。

比如,在三方库中最常见的,声明一个属性或者方法在当前版本弃用了

@property (strong,nonatomic)CLASSNAME * property __deprecated;

下面是 iOS开发中常见的几个 __attribute__ 用法:

//弃用API,用作API更新
#define __deprecated    __attribute__((deprecated))//带描述信息的弃用
#define __deprecated_msg(_msg) __attribute__((deprecated(_msg)))//遇到__unavailable的变量/方法,编译器直接抛出Error
#define __unavailable   __attribute__((unavailable))//告诉编译器,即使这个变量/方法 没被使用,也不要抛出警告
#define __unused    __attribute__((unused))//和__unused相反
#define __used      __attribute__((used))//如果不使用方法的返回值,进行警告
#define __result_use_check __attribute__((__warn_unused_result__))//OC方法在Swift中不可用
#define __swift_unavailable(_msg)   __attribute__((__availability__(swift, unavailable, message=_msg)))

Clang警告处理

当我们在XCode中屏蔽部分Warning信息时,可以使用下面的内容来解决。通过clang diagnostic push/pop来控制代码块的编译选项。

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
///代码
#pragma clang diagnostic pop

预处理

预处理可以让我们让我们自定义编译器变量,实现条件编译。 比如我们常用的DEBUG宏:

#ifdef DEBUG
//...
#else
//...
#endif

我们可以在XCode的Target中选中Build Setting选项,搜索proprecess,即可看到定义好的预处理宏。

07817ecb7f0affd487da58716a0c9afe.png

目前iOS基本都是用CocoaPods来管理工程,我们也可以在每个Pod的podspec文件中配置预编译宏,CocoaPods会在构建工程时将这些信息写到Pod的xcconfig文件里。

# Pod.podspec示例
s.subspec 'YourSubSpec' do | ss |ss.source_files = 'Pod/Classes/**/*'ss.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) YOUR_CUSTOM_DEFINE=1' }
end
注意:podA定义的GCC_PREPROCESSOR_DEFINITIONS内容在podB中是不生效的!!!
如果想解决这个问题,推荐podB中单独定义一个subspec来配置预编译宏的值,在外层工程里通过区分是否引入podB的subspec来实现该预编译宏值的控制。

Clang插件开发

上面介绍到语法分析之后我们可以拿到抽象语法树AST,接着就可以对这个树进行分析,做静态代码分析或者无用代码分析都可以,网上也有很多资料介绍这块的研究。感兴趣的可以搜索下或者看下 Introduction to the Clang AST

总结

以上内容主要介绍了下iOS编译相关的知识,如有内容错误,欢迎指正。

推荐 :

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS交流群:789143298 ,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!
  • ——点击加入:iOS开发交流群
  • BAT大厂面试题、独家面试工具包,
  • 资料免费领取,包括 数据结构、底层进阶、图形视觉、音视频、架构设计、逆向安防、RxSwift、flutter,

2cb7f7d3b167cfb2263495c666f899d5.png

原文作者:陈爱彬

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

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

相关文章

微信不再提供小程序打开App?借助H5为App引流的方式你必须知道!

简介&#xff1a; 2021年5月14日App开发者领域发布了一条重要消息&#xff1a;微信开放平台为了提升用户体验&#xff0c;将于2021年5月20日&#xff08;后来延期到2021年5月27日&#xff09;起不再提供“小程序打开App技术服务”&#xff0c;现在能够实现从微信打开App的方式只…

Gartner APM 魔力象限技术解读——全量存储? No! 按需存储?YES!

简介&#xff1a; 在云原生时代&#xff0c;充分利用边缘节点的计算和存储能力&#xff0c;结合冷热数据分离实现高性价比的数据价值探索已经逐渐成为 APM 领域的主流。 作者&#xff1a;夏明&#xff08;涯海&#xff09; 调用链记录了完整的请求状态及流转信息&#xff0c;是…

山石网科发布数据安全综合治理体系,覆盖数据全生命周期

编辑 | 宋慧 出品 | CSDN 云计算 11月24日&#xff0c;在“从一维到多维 &#xff0c;让数据安全有章可循——山石网科数据安全综合治理体系发布会”上&#xff0c;山石网科面向全行业推出《数据安全治理白皮书》&#xff0c;并向企业侧正式发布全新的数据安全治理体系和数据安…

android 获取cpu使用率_超详细的zabbix监控windows磁盘IO及cpu使用率教程

概述今天主要介绍怎么用zabbix来监控windows CPU使用率及磁盘IO&#xff0c;下面一起来看看吧~1、监控Windows-CPU使用率1.1、创建模板在zabbix中&#xff0c;默认的模板不带CPU使用率的监控&#xff0c;为减少重复工作率&#xff0c;在template模板下创建一个模板然后模板直接…

深入理解领域驱动设计中的聚合

简介&#xff1a; 聚合模式是 DDD 的模式结构中较为难于理解的一个&#xff0c;也是 DDD 学习曲线中的一个关键障碍。合理地设计聚合&#xff0c;能清晰地表述业务一致性&#xff0c;也更容易带来清晰的实现&#xff0c;设计不合理的聚合&#xff0c;甚至在设计中没有聚合的概念…

jenkins linux 发邮件,linuxea:jenkins pipeline邮件提醒的两种方式(5)

可以通过Mailer Plugin和Email-ext plugin插件发送邮件在pipeline中可以在执行完成进行&#xff0c;通过直接的结果发送失败或者成功&#xff0c;也可以在执行阶段过程中&#xff0c;如果在那个阶段执行失败发送&#xff0c;想看第一中&#xff0c;只发送失败的详细结果&#x…

致青春!一键上线你们专属的云上毕业纪念册

简介&#xff1a; 毕业不说再见&#xff0c;青春不散场&#xff01;在云端&#xff0c;在一起&#xff01;在问答https://developer.aliyun.com/ask/321737的留言区域晒出自己「线上环境」部署的毕业纪念册&#xff0c;在6月30号18点之前点赞数前10可以获得我们送出的毕业大礼包…

信息安全≠数据安全,山石网科发布2021《数据安全治理白皮书》

完整的数据安全治理体系&#xff0c;是一个包含了目标、组织、流程、技术等多维度的复杂系统工程。数据安全治理应该侧重四点&#xff1a;数据安全治理是必选项&#xff1b;是一套完整的治理体系问题&#xff1b;是多维视角的立体建构能力&#xff1b;是建立数据全生命周期的多…

dynamo python修改多个参数_40岁小白学了30天python发现,编程真的其乐无穷

今天是十一哥学python的第30天。时间过得挺快&#xff0c;感觉第一篇学习心得写了还没多久&#xff0c;这就已经不知不觉写30篇了。从第1集开始&#xff0c;看视频教程、记笔记、截图、写代码&#xff0c;然后写文章、配图、发帖、回复网友留言&#xff0c;以及在学习交流群里跟…

友盟+U-APM 移动应用性能体验报告:Android崩溃率达0.32%,OPPO 、华为、VIVO 崩溃表现良好

简介&#xff1a; 应用性能稳定是良好用户体验中非常关键的一环&#xff0c;而现实情况却是应用崩溃、卡顿、加载缓慢、页面白屏等问题&#xff0c;频频出现在用户的真实体验之中&#xff0c;成为影响业务表现的直接杀手。为此&#xff0c;应用性能管理&#xff08;APM&#xf…

阿里云张毅萍:构建边缘云全站加速网络体系

简介&#xff1a; 2021年6月9日&#xff0c;亚太内容分发大会暨CDN峰会在北京举行&#xff0c;阿里云边缘云网络高级技术专家张毅萍受邀参会&#xff0c;分享了阿里云在构建边缘云全站加速网络体系的实践&#xff0c;基于边缘云节点支撑各种应用协议的分层传输加速&#xff0c;…

http中的请求头各部分都是什么意思_硬核!30 张图解 HTTP 常见的面试题

每日一句英语学习&#xff0c;每天进步一点点&#xff1a;前言在面试过程中&#xff0c;HTTP 被提问的概率还是比较高的。小林我搜集了 5 大类 HTTP 面试常问的题目&#xff0c;同时这 5 大类题跟 HTTP 的发展和演变关联性是比较大的&#xff0c;通过问答 图解的形式由浅入深的…

Hologres揭秘:高性能原生加速MaxCompute核心原理

简介&#xff1a; Hologres技术揭秘系列持续更新中&#xff0c;本期我们将带来Hologres高性能原生加速查询MaxCompute的技术原理解析。 Hologres&#xff08;中文名交互式分析&#xff09;是阿里云自研的一站式实时数仓&#xff0c;这个云原生系统融合了实时服务和分析大数据的…

mfc 消息消息队列概念_消息队列面试连环问

最近我一直扎在消息队列实现细节之中无法自拔&#xff0c;已经写了 3 篇Kafka源码分析&#xff0c;还剩很多没肝完。之前还存着RocketMQ源码分析还没整理。今儿暂时先跳出来盘一盘大方向上的消息队列有哪些核心注意点。核心点有很多&#xff0c;为了更贴合实际场景&#xff0c;…

如何用增长的思维做提效?

简介&#xff1a; 埋点作为记录用户行为的常规手段&#xff0c;伴随着前端技术的发展早已历经春秋&#xff0c;不过直到“增长黑客”系列理论出现&#xff0c;才真正让埋点分析变得内涵丰富且有章可循。 作者 | 金戟 来源 | 阿里技术公众号 埋点作为记录用户行为的常规手段&am…

ajax返回list前台遍历_List、set集合接口分析

一、List接口详解1、List接口有三个实现类&#xff0c;ArrayList、LinkedList、Vector2、三个实现类的异同点&#xff1a;&#xff08;1&#xff09;ArrayList: 作为list接口的主要实现类&#xff1b;线程不安全&#xff0c;效率高&#xff1b;底层使用Object[]存储&#xff08…

聚焦 | 数据湖分析如何面向对象存储OSS进行优化?

简介&#xff1a; 最佳实践&#xff0c;以DLA为例子。DLA致力于帮助客户构建低成本、简单易用、弹性的数据平台&#xff0c;比传统Hadoop至少节约50%的成本。其中DLA Meta支持云上15种数据数据源&#xff08;OSS、HDFS、DB、DW&#xff09;的统一视图&#xff0c;引入多租户、元…

如何把极坐标化为直角坐标_2019高考100题之063(极坐标)

分析&#xff1a;如果你对过原点的直线的参数方程(xtcosθ&#xff0c;ytsinθ(参数t∈R))理解透彻了&#xff0c;那么极坐标也就没有任何问题了&#xff0c;特别是对于ρ<0的理解&#xff0c;就和t<0类似.教材上说了不作特殊说明&#xff0c;ρ都是大于零的&#xff0c;…

c语言队列作用,队列(C语言)

一、定义一种可以实现“先进先出”的存储结构。二、分类1、链式队列&#xff1a;用链表实现。2、静态队列&#xff1a;用数组实现。静态队列通常都必须是循环队列。3、循环队列(1)循环队列需要几个参数来确定&#xff1f;需要2个参数来确定&#xff1a;front、rear(2)循环队列各…

2021银行共探转型新动能:大行酝酿质变 小行跨越数字鸿沟

2021年&#xff0c;我国“十四五”规划开篇启程&#xff0c;数字经济蓬勃发展&#xff0c;银行业紧跟国家发展大局&#xff0c;全力推进数字化转型向纵深发展&#xff0c;探寻行业新动能&#xff0c;积极参与全社会数字生态建设&#xff0c;为数字中国高质量发展贡献金融力量。…