简易C语言编译器源码-其他:Java可以是跨平台的,但是C呢?

当我们第一次学习Java时,我们的老师总是告诉我们Java的优势之一:跨平台特性。相反,为什么C/CPP语言不能跨平台?作者查阅了以下内容,印象深刻。本文由两部分组成:

1.C语言程序不是跨平台的原因

2. 简要了解 Java 的字节码文件结构

作者对计算机系统和原理的理解有限,因此理解存在错误。同时感谢线上高手们的无私经验分享~

从类文件中深入了解 Java 字节码结构

汇编语言和高级语言

为什么C不能跨平台

深入了解 Java 虚拟机 (3) – 字节码文件格式和类加载

可执行文件的诞生

众所周知,无论你用什么语言实现Hello World程序,计算机能理解的最后一件事一定是由纯二进制代码组成的机器语言。包括我们此刻的QQ聊天,或者腾讯发布会,这些程序都只是CPU级别的一系列0101码。如果深入硬件级别,它是一个非门电路。

感谢这么多很棒的IDE(例如Visual Studio,Code Blocks),使编译.c文件变得容易和愉快,我们只需单击运行按钮,源文件就会被手动编译和执行,例如hello.c:one

#include 
int main(){printf("hello,c!");return 0;}

IDE 实际上为我们执行了此过程:

总之,这个Hello.c经历了预处理、编译、汇编、链接的过程,最后生成出一个可以直接执行的二进制文件。

汇编语言

汇编语言是用于电子计算机、微处理器、微控制器或其他可编程组件的低级语言。在不同的设备中,汇编语言对应于不同的机器语言指令集。汇编语言专用于某种计算机系统结构,不像许多高级语言,它可以在不同的系统平台之间移植。

在计算机诞生之初(直到今天),计算机只知道 0 或 1。那个时代的科学家只能通过在纸带上打孔来告诉计算机:孔代表1,反之亦然是0。这样,人机交互终于实现了,但效率却催人泪下。

科学家们已经意识到,无论程序多么复杂,计算机指令的数量都是有限的,唯一的区别是数据的差异。该命令需要由芯片固定和识别,芯片是使用由管组成的非栅极电路的组合来实现的。

所以科学家后来发明了汇编语言,针对这种固定的指令,用符号代替繁琐的01代码,代码的可读性得到了很大的提高。

在汇编程序之后

完成后,需要一个特殊的程序(汇编程序)将编译后的汇编程序编译为 0 和 1。

但一个新的问题出现了:不同公司生产的CPU芯片有不同的指令集(比如以Intel为代表的复杂指令集阵营,以ARM为代表的简化指令集阵营,不同公司设计指令集的思路完全不同)。

高级语言

随着程序变得越来越多

复杂,当时的程序员越来越渴望一种新的编程语言:它不依赖于计算机硬件,人们可以使用统一的书写方法来实现编程,而不管计算机模型如何。

1954年,第一个成熟的中级编程语言FORTRAN诞生了。从那时起,编程已经从特定机器的限制中移除。自第一种编程语言诞生以来,已经诞生了数百种中间语言,如C,BASIC,CPP,包括Java。

当我们使用C进行编程时,我们首先使用编译器将源文件编译成汇编器,然后使用汇编器将其编译为0,1。一个可执行文件诞生了。

交叉硬件是不够的

尽管中间语言帮助程序员实现了跨硬件的飞跃,但随着操作系统的普及,问题出现了:相同的.c文件在不同的平台上可能以不同的方式运行。

原因是不同平台使用的编译器并不完全相同。例如,一些编译器为相同 int 类型的数据分配 2 个字节的空间,而另一些编译器为其分配 4 个字节的空间。因此,在平台 A 中正常运行的程序在平台 B 上可能会出现内存溢出错误。

在不同的平台上,同一个Hello.c的最终编译的文件格式是不同的:

我们在Windows上使用的应用程序是编译程序

大多数网民都在使用或使用Microsoft的Windows系统。俗话说,需求是有市场的:软件开发人员在Windows平台上开发软件,最后向用户交付一个包含可执行文件.exe的文件夹。

这个.exe文件其实是从Windows平台下的源文件编译生成的可执行二进制文件,Windows用户运行它们自然没有问题。

为了用户体验,用户只关心一件软件就可以正常使用。出于盈利原因,一些供应商不发布他们的源代码,因为这相当于向其他人宣布了所有技术细节。

但是,当放置在 Linux 平台下时,此.exe及其依赖项能否正常工作?恐怕不是。

有时需要自动编译源代码

对于开源软件,官网通常会提供软件的源码文件下载包,或者留下GitHub链接。

开发人员有时会从官方网站下载源文件,并在执行之前通过其平台的本机 C 编译器(例如 gcc 等工具)编译二进制文件,这些文件需要花费平台可执行文件,特别是对于那些使用 Linux 作为开发环境的人。这就好比去市场卖菜

:市场卖的是一样的菜,根据大家的口味,这些同样的菜是出手做的,做的菜也不一样。

在计算机中,这种差异突出了平台或处理器型号,因此用同一 C 语言编译的代码在不同的环境中可能会以不同的方式运行。由于这种差异,C/CPP 语言不是跨平台的。在这些情况下,我们必须下载源代码并使用相应的编译工具自动编译它,使其适应我们的操作环境。

例如,如果我们想在 Linux 环境中使用 Redis 工具,我们需要先使用 make 命令编译它,然后才能使用它。

Hadoop还建议下载源代码并在使用前使用编译器进行编译。

考虑到性能问题和缺少单独的Java泛型,Hadoop为各个组件提供了自己的本机实现。这些组件存储在Hadoop中单独的动态链接存储库中。这个库在 *nix 平台上被称为 libhadoop.so

Hadoop是用Java开发的,但是有一些要求和操作不适合Java,因此引入了原生库的概念。坦率地说,Hadoop的各个功能必须与Java类文件和通过JNT的本机代码生成的库文件一起工作。要在 Linux 系统上运行本机代码,必须首先将本机编译为目标 CPU 体系结构的 [.so] 文件。不同的处理器架构需要编译对应平台的动态库[.so]文件才能正确执行,所以最好重新编译一次Hadoop源代码,让[.so]文件对应自己的处理器。

本地库,

通常翻译为本机库或本机库简易C语言编译器源码,是用 C/C++ 编译的动态库 [.so],通过 JNI(Java 原生接口)机制为 Java 层提供了一个出口。应用程序通常提供套接字,用于在 C/C++ 中实现相关逻辑并编译到较低层或其他模块的库中,以调用性能和安全考虑。

链接到此声明

Hadoop的官方网站解释了原生库

跨平台语言Java诞生了

通过前三节,我们了解到 C/C++ 语言一直受到跨平台的限制。有没有办法让高级语言跨平台运行?

我们考虑实际应用环境;如果后端正在传输 XML 格式的文件,而后端最终需要以 JSON 格式存储数据,该怎么办?让我们创建一个适配器适配器并在数据传输之前转换XML和json文件!这是典型的适配器设计模式。

Java伴随着它的虚拟机JVM而来。它与C/CPP语言的最大区别在于,首先,Java代码在JVM虚拟机上运行。其次,编译此 Java 代码不是生成纯二进制机器指令,而是生成非二进制字节码文件.class。并且此文件与计算机的硬件或平台无关,仅与JVM有关。

真正赋予Java跨平台特性的是JVM虚拟机。

只有JVM才能理解.class字节码文件的真正含义,将其正确转换为机器代码并执行。换句话说,无论是在Linux还是Windows上,只要安装了适配的JVM虚拟机,Java代码就可以顺利执行。

对于Java程序员来说,他不再需要考虑javac编译的字节码文件应该运行哪个平台,反正他只需要安装相应平台的JDK环境:不管那个平台的JVM来执行代码,都要求字节码文件的结构是相同的格式。

笔者认为,虚拟机和虚拟容器技术后续发展的核心思想与JVM没有什么不同,即:适配器设计模式。

JVM 机器如何理解类文件?

井。。。。。。研究JVM也是一种形而上学。由于作者的水平和精力有限,笔者决定在随后的JVM研究中补充这部分的详细内容。

在我的第一篇博客中简易C语言编译器源码,我简要提到了.class文档的内容。(为什么用txt打开.class文件会乱码,而打开.java文件却没有?这一次,让我们从不同的角度看一下.class文件的内部:

首先我们需要安装 NotePad++,然后安装 HexEditor_0.9.6_x64 插件,以确保我们以十六进制格式读取.class文件。具体安装很简单,笔者就不赘述了。

我们使用NotePad++编译一个简单的JavaClass .java文件:

class JavaClass {
    public static void main(String[] args){
        System.out.println("Hello Java");
    }   
}

然后通过javac生成相应的Java .class文件并打开它:

一个简单的代码句子被压缩成 16 个符号中的一大串数字和字母。 其中 xx 表示 1 个字节。由于 JVM 也可以基于此符号将 Hello Java 输出到控制台,因此意味着此符号必须违反特定规则:即 Java 虚拟机规范。

NotePad++添加了HEX编辑器插件

字节码结构

我们可以参考这个表结构来翻译我们的 HelloJava .class文件。

类型名称描述宽度

U4

魔法

幻数,识别类文件格式

4 字节

U2

minor_version

次要版本号

2 字节

U2

major_version

主版本号

2 字节

U2

constant_pool_count

恒池计算器

2 字节

cp_info

constant_pool

恒定池

n 字节

U2

access_flags

访问标志

2 字节

U2

this_class

类索引

2 字节

U2

super_class

父类索引

2 字节

U2

interfaces_count

接口计数器

2 字节

U2

接口

接口索引集合

2 字节

U2

fields_count

字段数

2 字节

field_info

领域

字段集合

n 字节

U2

methods_count

方法计数器

2 字节

method_info

方法

方法的集合

n 字节

U2

attributes_count

其他属性计数器

2 字节

attribute_info

属性

附加属性的集合

n 字节

根据 Java 字节码结构表,我们可以解析 NotePad++ 显示的十六进制文件中包含的信息。此外,我们可以从这个表中看到.class文件只有两种数据类型:无符号数字和表。

数据类型定义说明

无符号号码

无符号数字可用于描述数字、索引引用、数量值或根据 UTF-8 编码的字符串值。

其中无符号数字是基本数据类型。U1、U2、U4 和 U8 分别表示 1 字节、2 字节、4 字节和 8 字节

桌子表

是由多个无符号数字或其他表组成的复合数据结构。

所有表都以“_info”结尾。由于表格没有固定的宽度,因此它们通常后跟数字说明。

从这两个表中,我们可以看到,即使是 HelloWorld 级别的.class也包含如此多的内容。表中的每个结构都值得讨论,当我即将研究.class和 JVM 原则时,我将仔细研究它。

当然,我们也可以使用javap命令来剖析。 javap 是 JDK 自带的反编译工具,可以解析当前类对应的代码区(汇编指令)、局部变量表、异常表和代码行偏移映射表、常量池等信息。

$ javap -verbose JavaClass.class

该程序最终将返回:

Classfile /C:/Users/liJunhu/Desktop/x学习笔记/Scala分支/scalaTest/JavaClass.class
  Last modified 2020-5-28; size 422 bytes
  MD5 checksum 75803102330020b05d871810e7dbe63c
  Compiled from "JavaClass.java"
class JavaClass
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#15         // java/lang/Object."":()V
   #2 = Fieldref           #16.#17        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #18            // Hello Java
   #4 = Methodref          #19.#20        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #21            // JavaClass
   #6 = Class              #22            // java/lang/Object
   #7 = Utf8               
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               SourceFile
  #14 = Utf8               JavaClass.java
  #15 = NameAndType        #7:#8          // "":()V
  #16 = Class              #23            // java/lang/System
  #17 = NameAndType        #24:#25        // out:Ljava/io/PrintStream;
  #18 = Utf8               Hello Java
  #19 = Class              #26            // java/io/PrintStream
  #20 = NameAndType        #27:#28        // println:(Ljava/lang/String;)V
  #21 = Utf8               JavaClass
  #22 = Utf8               java/lang/Object
  #23 = Utf8               java/lang/System
  #24 = Utf8               out
  #25 = Utf8               Ljava/io/PrintStream;
  #26 = Utf8               java/io/PrintStream
  #27 = Utf8               println
  #28 = Utf8               (Ljava/lang/String;)V
{
  JavaClass();
    descriptor: ()V
    flags:
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."":()V
         4: return
      LineNumberTable:
        line 1: 0
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello Java
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 5: 0
        line 6: 8
}
SourceFile: "JavaClass.java"

一个小小的复活节彩蛋

让我们仔细看看这个十进制 16 文件的前 4 个字节:

嗯,它的价值0xCAFE宝贝。它的价值和名字一样有趣。幻数是用于区分文件类型的符号,通常由文件的前几个字节表示。例如0xCAFE BABE 表示类文件,那么为什么不使用文件名后缀呢?由于文件名后缀很容易更改,为了保证文件的安全性,在文件内部写入文件类型可以保证它不被篡改。至于为什么类文件使用0xCAFE宝贝...

文章永久链接:

简介 1.1 什么是C语言?

C是一种面向过程的抽象通用编程语言,广泛用于低级开发。

C语言可以以简单的形式编译和处理低级内存。C 是一种高效的编程语言,仅形成少量的机器语言,可以在没有任何运行时环境支持的情况下运行。虽然C提供了许多低级处理功能,但它仍然是跨平台的,以标准大小编写的C程序可以在许多计算机平台上编译,包括嵌入式处理器和超级计算机等操作平台。

冯.诺依曼在1945年提出了几个现代计算机的想法,后来被称为冯曼。诺依曼思想,这是计算机发展史上的一个里程碑。自1945年至今,大部分采用其结构,因此冯.诺依曼被称为计算机之父。他的建筑计算机由五个组件组成:运算器、控制器、存储器、输入设备和输出设备。C语言拥有完整的理论体系,经过漫长的发展历史,在编程语言中具有举足轻重的地位。

C 是

出生于日本贝尔实验室,由D.M. Ritchie基于B语言开发,在其主要设计完成后,Thompson和Ritchie完全重绘了UNIX,随着UNIX的发展,C语言也不断建立。为了便于C语言的全面推广,众多专家学者和硬件厂商共同组成了C语言标准委员会,并于1989年诞生了第一个完整的C标准,简称“C89”,即“ANSIc”。

1.2 C语言与其他编程语言的比较

C 不同于面向对象的编程语言,如 C++ 和 Java。C 的目标是提供一种编程语言,该语言可以以简单形式编译,处理低级内存,形成少量机器代码,并在没有任何运行时支持的情况下运行。C语言描述问题的速度比汇编语言快简易C语言编译器源码,工作量少,可读性强,易于调试、修改和移植,代码质量堪比汇编语言。C语言通常只比汇编语言代码生成的目标程序低10%~20%。为此,C可以对系统软件进行编程。

现阶段,在编程领域,C语言使用非常多,具有中间语言汇编语言的优点,与其他编程语言相比有很大的优势。计算机系统设计和应用程序编程是C语言应用的两个主要领域。同时,C语言的普遍适用性强,可以应用于许多计算机操作系统,效率明显。

一般来说,每种编程语言都有自己的优点和价值;C是一种硬件友好的语言,可用于对操作系统进行编程,因此C适合开发追求运行速度并充分发挥硬件性能的程序。

记住:毕竟语言只是工具,算法是核心,思想是灵魂。

用任何编程语言开发程序都是让计算机做指定的事情,比如:删除单个文件、下载文件、编译文档等;计算机的CPU只知道机器指令,所以虽然不同的编程语言差别很大,但都要“翻译”成CPU可以执行的机器指令。而不同的编程语言,做同样的事情,编译的代码量,也大不相同。

1.3 C语言的特点

(1)语言简洁,紧凑,使用方便灵活。C共有32个关键词,9个控制句,程序编写自由,压缩了所有不必要的组件。

(2)运营商丰富。

(3)数据类型丰富,具有现代语言的各种数据结构。

(4)有结构化的控制句。

(5)语法限制不严格,程序设计自由度大。

(6)C语言允许直接访问数学地址、位运算,可以实现汇编语言的大部分功能,可以直接在硬件上运行。

(7)生成的目标代码质量高,程序执行效率高。C 的效率通常仅比汇编程序生成的目标代码低 10%-%20。

(8)用C语言编写的程序是可移植的,可以在各种平台上运行,无需太多更改。

1.4 C语言应用的现状

(1)C语言几乎是操作系统内核开发领域唯一的开发工具,大多数操作系统都是由C语言加上少量汇编语言开发的;例如:Linux,Windows,Vxworks,Unix。

(2)在嵌入式领域具有绝对优势。

(3)Apache、Oracle在网络服务器类方面有相当的优势。

(4)使用C的GUI应用和大规模商业程序的应用很多。例如:Offices,SPSS,AutoCAD。

(5)大规模、高性能的评估、游戏开发,以及一些传统的客户端软件和预制组件。

1.5 编译C代码的推荐编辑器

C语言

是一种跨平台的编程语言,在Windows系统中,Linux系统是可以学习的,下面介绍学习C语言,编译C语言代码是比较方便的一些工具软件。

(1)可视化工作室代码

Microsoft 2015 年 4 月 30 日的 Build 开发者大会上宣布了 Visual Studio Code 项目:一个跨平台源代码编辑器,用于编写在 MacOSX、Windows 和 Linux 上运行的现代 Web 和云应用程序。

下载地址:

图 1-5-1

图 1-5-2

(2)记事本++

记事本(Notepad)是Windows中用于文本编辑的代码编辑器或小程序,在文本编辑方面可与Windows写字板相媲美。 是一个开源的,小型的,免费的纯文本编辑器。

下载地址:

图 1-5-3

(4)崇高文字

SublimeText3是一款流行的代码编辑器软件和高级文本编辑器,适用于在Linux,Windows和MacOSX上运行的HTML和诗歌。它也是许多程序员喜欢使用的文本编辑器软件。

下载地址:

图 1-5-4

二、在Windows系统下构建C语言学习环境2.1,安装VSCode代码编辑器

Visual StudioCode是Google的跨平台源代码编辑器,它可以轻松地用各种编程语言编写代码。

下载地址:

图 2-1-1

图 2-1-2

下载安装包后,直接双击键盘运行。

图 2-1-3

图 2-1-4

图 2-1-5

图 2-1-6

图 2-1-7

图 2-1-8

图 2-1-9

图 2-1-10

安装软件后简易C语言编译器源码,以下设置 Visual Studio 支持英语

首先打开Visual Studio软件并按F1或Shift+Ctrl + P:

然后在命令行上键入配置显示语言

图 2-1-11

选择安装语言选项。

图 2-1-12

安装完成后,右下角有重启提示,单击重启。

图 2-1-13

图 2-1-14

软件发布后安装

完毕后,创建一个新的.c文件并保存到指定目录下;此时,软件右下角会提示安装C/C++扩展支持,单击安装。

下面介绍修改颜色 vscode 的颜色主题。

图 2-1-15

图 2-1-16

2.2Mingw-w64编译器下载

VSCode 只是一个编辑器,而不是 IDE(集成开发环境);编译器(和许多其他功能)不包括在内,要编译 C/C++ 程序,您需要单独下载编译器。

在Windows下,Mingw-w64工具集通常用于构建C语言开发环境;

Mingw-w64 在 Windows 下提供了一个 C 开发环境,工具集包括头文件、库、运行时和一些工具,支持 64 位开发,是 MinGW 的升级项目。

虽然明·

和MinGW-w64只是子名称,它们是两个不同的项目;MinGW本身已经很久没有更新了,所以不推荐。

官方 Vscode 说明和使用文档:

窗口下的MinGW离线安装包下载地址:

提取代码:5m6k

注意:这是 win10_64 位系统的 MinGW。

图 2-2-1

下载的软件包的名称:i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z

2.3 为系统环境变量添加编译器路径建议

将压缩包解压到指定目录,建议存储在C盘上,在C盘创建名为“MinGW”的目录。

图 2-3-1

将 gcc/g++ 可执行文件的路径添加到系统环境变量中。

图 2-3-2

图 2-3-3

图 2-3-4

图 2-3-5

图 2-3-6

图 2-3-7

图 2-3-8

图 2-3-9

2.4 测试编译器

打开 vscode 编译代码,编写代码,在终端中编译运行。

图 2-4-1

图 2-4-2

2.5 vscode 终端中的 PowerShell 简介

Windows下的Vscode外部终端使用PowerShell。

图 2-5-1

PowerShell,作为

名称可以知道,它首先是一个shell,shell的意思与Linux bash相同,并且原始cmd是通过在其上键入命令(可执行文件)来使用的;

而力量意味着他是一个强大的外壳,从用户的角度来看,我个人认为它的力量突出在以下几个方面:

(1)谷歌心态。谷歌正在真正实现PowerShell,包括Office等更多的是自己的软件,底层叫做PowerShell来实现。

PowerShell包含前一个cmd的所有命令,原始命令的使用方式相同,但命令被添加到其之上。

(3)基准测试Linux。PowerShell使用LinuxShell的思想,即所有系统操作和配置都可以通过在shell中键入命令来实现。

(4)统一的命令格式和独立的文档。基于前3点,我们可以说PowerShell可以与LinuxBash等竞争,如果加上后来者的优势,你可以相信PowerShell能够成功。

其实PowerShell很好,但它也有它的缺点:

(1)Linux和Windows系统本身定位的差异。Linux的自由稳定性使其牢牢占据服务器领域,LinuxShell命令没有很多统一的格式;工程师们很难学会这一点,当Linux占用工程师的大部分精力并养成他们的习惯时,工程师似乎没有学习PowerShell的精神和动力。

(2)来自Windows GUI的竞争。GUI可以做Windows上的命令也可以更有效地完成的所有事情,但普通用户不想去一个昏暗的界面来键入感觉不受控制的命令。

2.6VSCode英语输出乱码解决方案

文件 >> 首选项 >> 设置
搜索:
"files.autoGuessEncoding": false
改为:
"files.autoGuessEncoding": true
然后出去将.c代码文件改为GB2312编码保存,再使用VSccode打开即可。

图 2-6-1

图 2-6-2

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 源码编译 简易C语言编译器源码-其他:Java可以是跨平台的,但是C呢? https://www.wkzy.net/game/131773.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务