是否依赖于 C++ 平台?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11810484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is C++ platform dependent?
提问by Sanjaya Pandey
Can we say that C++ is platform dependent?
我们可以说 C++ 是平台相关的吗?
I know that C++ uses compiler, and those compiler are different for different platforms. When we compile C++ code using compiler for example: on Windows, .EXEformat file created.
我知道 C++ 使用编译器,这些编译器针对不同的平台是不同的。例如,当我们使用编译器编译 C++ 代码时:在 Windows 上,创建了.EXE格式的文件。
Why is an .EXEfile OS/Platform dependent?
为什么.EXE文件依赖于操作系统/平台?
What is the format inside .EXE files?
.EXE 文件中的格式是什么?
Why can't we run it on other platforms?
为什么我们不能在其他平台上运行它?
回答by RageD
This is actually a relatively extensive topic. For simplicity, it comes down to two things: operating system and CPU architecture.
这其实是一个比较广泛的话题。为简单起见,它归结为两件事:操作系统和 CPU 架构。
First of all, *.exe is generally only Windows since it is binarycode which the windows operating system knows how to execute. Furthermore, the operating system knows how to translate this to the proper code for the architecture (this is why Windows is "just compatible"). Note that a lot more is going on, but this is a (very) high-level abstraction of what is going on.
首先,*.exe 通常只是 Windows,因为它是Windows 操作系统知道如何执行的二进制代码。此外,操作系统知道如何将其转换为体系结构的正确代码(这就是 Windows“仅兼容”的原因)。请注意,还有很多事情正在发生,但这是对正在发生的事情的(非常)高级抽象。
Now, compilers will take C++ code and generate its corresponding assembly code for the architecture (i.e. x86, MIPS, etc.). Usually the compiler also has an assembler (or one which it can rely on). The assembler the links code and generates binary code which the hardware can execute. For more information on this topic look for more information on co-generation.
现在,编译器将采用 C++ 代码并为体系结构(即 x86、MIPS 等)生成其相应的汇编代码。通常编译器也有一个汇编器(或一个它可以依赖的汇编器)。汇编程序链接代码并生成硬件可以执行的二进制代码。有关此主题的更多信息,请查找有关热电联产的更多信息。
Additional Note
附加说明
Consider Java which is not platform-dependent. Java compilers generate Java bytecode which is run on the Java virtual machine (JVM). It is important to notice that any time you wish to run a Java application you must run the Java virtual machine. Since the precompiled JVM knows how to operate on your operating system and CPU architecture, it can run its Java bytecode and effectively run the corresponding actions for your particular system.
考虑不依赖于平台的 Java。Java 编译器生成在 Java 虚拟机 (JVM) 上运行的 Java 字节码。需要注意的是,无论何时您希望运行 Java 应用程序,您都必须运行 Java 虚拟机。由于预编译的 JVM 知道如何在您的操作系统和 CPU 架构上运行,因此它可以运行其 Java 字节码并有效地为您的特定系统运行相应的操作。
In a compiled binary file (i.e. one from C++ code), you have system bytecode. So the kind of instructions which Java simulates for you are directly hard-coded into the .exe or whatever binary format you are using. Consider the following example:
在已编译的二进制文件(即来自 C++ 代码的文件)中,您有系统字节码。因此,Java 为您模拟的指令类型直接硬编码到 .exe 或您使用的任何二进制格式中。考虑以下示例:
Notice that this java code must eventually be run in the JVM and cannot stand-alone.
请注意,此java代码最终必须在JVM中运行,不能独立运行。
Java Code:
System.out.println("hello") (To be compiled)
Compiled Java bytecode:
Print "hello" (To be run in JVM)
JVM:
(... some translation, maybe to architecture code - I forget exactly ...)
system_print_code "hello" (JVM translation to CPU specific)
Versus the C++ (which can be run in stand-alone mode):
与 C++(可以在独立模式下运行):
C++ Code:
cout<< "hello";
Architecture Code:
some_assembly_routine "hello"
Binary output:
system_print_code "hello"
A real example
一个真实的例子
If you're curious about how this may actually look in a real-life example, I have included one below.
如果您对实际示例中的实际情况感到好奇,我在下面包含了一个。
C++ SourceI placed this in a file called hello.cpp
C++ 源代码我把它放在一个名为 hello.cpp 的文件中
#include <iostream>
int main() {
using namespace std;
cout << "Hello world!" << endl;
return 0;
}
Assembly (Generated from C++ source)Generated via g++ -S hello.cpp
程序集(从 C++ 源代码生成)通过g++ -S hello.cpp
.file "test.c"
.section .rodata
.type _ZStL19piecewise_construct, @object
.size _ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
.zero 1
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.LC0:
.string "Hello world!"
.text
.globl main
.type main, @function
main:
.LFB1493:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rsi
leaq _ZSt4cout(%rip), %rdi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
movq %rax, %rdx
movq _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
movq %rax, %rsi
movq %rdx, %rdi
call _ZNSolsEPFRSoS_E@PLT
movl 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0100 3e00 0100 0000 0000 0000 0000 0000 ..>.............
00000020: 0000 0000 0000 0000 0807 0000 0000 0000 ................
00000030: 0000 0000 4000 0000 0000 4000 0f00 0e00 ....@.....@.....
00000040: 5548 89e5 488d 3500 0000 0048 8d3d 0000 UH..H.5....H.=..
00000050: 0000 e800 0000 0048 89c2 488b 0500 0000 .......H..H.....
00000060: 0048 89c6 4889 d7e8 0000 0000 b800 0000 .H..H...........
00000070: 005d c355 4889 e548 83ec 1089 7dfc 8975 .].UH..H....}..u
00000080: f883 7dfc 0175 3281 7df8 ffff 0000 7529 ..}..u2.}.....u)
00000090: 488d 3d00 0000 00e8 0000 0000 488d 1500 H.=.........H...
000000a0: 0000 0048 8d35 0000 0000 488b 0500 0000 ...H.5....H.....
000000b0: 0048 89c7 e800 0000 0090 c9c3 5548 89e5 .H..........UH..
000000c0: beff ff00 00bf 0100 0000 e8a4 ffff ff5d ...............]
000000d0: c300 4865 6c6c 6f20 776f 726c 6421 0000 ..Hello world!..
000000e0: 0000 0000 0000 0000 0047 4343 3a20 2847 .........GCC: (G
000000f0: 4e55 2920 372e 322e 3120 3230 3137 3131 NU) 7.2.1 201711
00000100: 3238 0000 0000 0000 1400 0000 0000 0000 28..............
00000110: 017a 5200 0178 1001 1b0c 0708 9001 0000 .zR..x..........
00000120: 1c00 0000 1c00 0000 0000 0000 3300 0000 ............3...
00000130: 0041 0e10 8602 430d 066e 0c07 0800 0000 .A....C..n......
00000140: 1c00 0000 3c00 0000 0000 0000 4900 0000 ....<.......I...
00000150: 0041 0e10 8602 430d 0602 440c 0708 0000 .A....C...D.....
00000160: 1c00 0000 5c00 0000 0000 0000 1500 0000 ....\...........
00000170: 0041 0e10 8602 430d 0650 0c07 0800 0000 .A....C..P......
00000180: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000190: 0000 0000 0000 0000 0100 0000 0400 f1ff ................
000001a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001b0: 0000 0000 0300 0100 0000 0000 0000 0000 ................
000001c0: 0000 0000 0000 0000 0000 0000 0300 0300 ................
000001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001e0: 0000 0000 0300 0400 0000 0000 0000 0000 ................
000001f0: 0000 0000 0000 0000 0000 0000 0300 0500 ................
00000200: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000210: 0800 0000 0100 0500 0000 0000 0000 0000 ................
00000220: 0100 0000 0000 0000 2300 0000 0100 0400 ........#.......
00000230: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000240: 3200 0000 0200 0100 3300 0000 0000 0000 2.......3.......
00000250: 4900 0000 0000 0000 6200 0000 0200 0100 I.......b.......
00000260: 7c00 0000 0000 0000 1500 0000 0000 0000 |...............
00000270: 0000 0000 0300 0600 0000 0000 0000 0000 ................
00000280: 0000 0000 0000 0000 0000 0000 0300 0900 ................
00000290: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002a0: 0000 0000 0300 0a00 0000 0000 0000 0000 ................
000002b0: 0000 0000 0000 0000 0000 0000 0300 0800 ................
000002c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002d0: 7100 0000 1200 0100 0000 0000 0000 0000 q...............
000002e0: 3300 0000 0000 0000 7600 0000 1000 0000 3.......v.......
000002f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000300: 8000 0000 1000 0000 0000 0000 0000 0000 ................
00000310: 0000 0000 0000 0000 9600 0000 1000 0000 ................
00000320: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000330: ce00 0000 1000 0000 0000 0000 0000 0000 ................
00000340: 0000 0000 0000 0000 0901 0000 1000 0000 ................
00000350: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000360: 1a01 0000 1000 0000 0000 0000 0000 0000 ................
00000370: 0000 0000 0000 0000 3201 0000 1002 0000 ........2.......
00000380: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000390: 3f01 0000 1000 0000 0000 0000 0000 0000 ?...............
000003a0: 0000 0000 0000 0000 5701 0000 1000 0000 ........W.......
000003b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003c0: 0074 6573 742e 6300 5f5a 5374 4c31 3970 .test.c._ZStL19p
000003d0: 6965 6365 7769 7365 5f63 6f6e 7374 7275 iecewise_constru
000003e0: 6374 005f 5a53 744c 385f 5f69 6f69 6e69 ct._ZStL8__ioini
000003f0: 7400 5f5a 3431 5f5f 7374 6174 6963 5f69 t._Z41__static_i
00000400: 6e69 7469 616c 697a 6174 696f 6e5f 616e nitialization_an
00000410: 645f 6465 7374 7275 6374 696f 6e5f 3069 d_destruction_0i
00000420: 6900 5f47 4c4f 4241 4c5f 5f73 7562 5f49 i._GLOBAL__sub_I
00000430: 5f6d 6169 6e00 5f5a 5374 3463 6f75 7400 _main._ZSt4cout.
00000440: 5f47 4c4f 4241 4c5f 4f46 4653 4554 5f54 _GLOBAL_OFFSET_T
00000450: 4142 4c45 5f00 5f5a 5374 6c73 4953 7431 ABLE_._ZStlsISt1
00000460: 3163 6861 725f 7472 6169 7473 4963 4545 1char_traitsIcEE
00000470: 5253 7431 3362 6173 6963 5f6f 7374 7265 RSt13basic_ostre
00000480: 616d 4963 545f 4553 355f 504b 6300 5f5a amIcT_ES5_PKc._Z
00000490: 5374 3465 6e64 6c49 6353 7431 3163 6861 St4endlIcSt11cha
000004a0: 725f 7472 6169 7473 4963 4545 5253 7431 r_traitsIcEERSt1
000004b0: 3362 6173 6963 5f6f 7374 7265 616d 4954 3basic_ostreamIT
000004c0: 5f54 305f 4553 365f 005f 5a4e 536f 6c73 _T0_ES6_._ZNSols
000004d0: 4550 4652 536f 535f 4500 5f5a 4e53 7438 EPFRSoS_E._ZNSt8
000004e0: 696f 735f 6261 7365 3449 6e69 7443 3145 ios_base4InitC1E
000004f0: 7600 5f5f 6473 6f5f 6861 6e64 6c65 005f v.__dso_handle._
00000500: 5a4e 5374 3869 6f73 5f62 6173 6534 496e ZNSt8ios_base4In
00000510: 6974 4431 4576 005f 5f63 7861 5f61 7465 itD1Ev.__cxa_ate
00000520: 7869 7400 0000 0000 0700 0000 0000 0000 xit.............
00000530: 0200 0000 0500 0000 fdff ffff ffff ffff ................
00000540: 0e00 0000 0000 0000 0200 0000 0f00 0000 ................
00000550: fcff ffff ffff ffff 1300 0000 0000 0000 ................
00000560: 0400 0000 1100 0000 fcff ffff ffff ffff ................
00000570: 1d00 0000 0000 0000 2a00 0000 1200 0000 ........*.......
00000580: fcff ffff ffff ffff 2800 0000 0000 0000 ........(.......
00000590: 0400 0000 1300 0000 fcff ffff ffff ffff ................
000005a0: 5300 0000 0000 0000 0200 0000 0400 0000 S...............
000005b0: fcff ffff ffff ffff 5800 0000 0000 0000 ........X.......
000005c0: 0400 0000 1400 0000 fcff ffff ffff ffff ................
000005d0: 5f00 0000 0000 0000 0200 0000 1500 0000 _...............
000005e0: fcff ffff ffff ffff 6600 0000 0000 0000 ........f.......
000005f0: 0200 0000 0400 0000 fcff ffff ffff ffff ................
00000600: 6d00 0000 0000 0000 2a00 0000 1600 0000 m.......*.......
00000610: fcff ffff ffff ffff 7500 0000 0000 0000 ........u.......
00000620: 0400 0000 1700 0000 fcff ffff ffff ffff ................
00000630: 0000 0000 0000 0000 0100 0000 0200 0000 ................
00000640: 7c00 0000 0000 0000 2000 0000 0000 0000 |....... .......
00000650: 0200 0000 0200 0000 0000 0000 0000 0000 ................
00000660: 4000 0000 0000 0000 0200 0000 0200 0000 @...............
00000670: 3300 0000 0000 0000 6000 0000 0000 0000 3.......`.......
00000680: 0200 0000 0200 0000 7c00 0000 0000 0000 ........|.......
00000690: 002e 7379 6d74 6162 002e 7374 7274 6162 ..symtab..strtab
000006a0: 002e 7368 7374 7274 6162 002e 7265 6c61 ..shstrtab..rela
000006b0: 2e74 6578 7400 2e64 6174 6100 2e62 7373 .text..data..bss
000006c0: 002e 726f 6461 7461 002e 7265 6c61 2e69 ..rodata..rela.i
000006d0: 6e69 745f 6172 7261 7900 2e63 6f6d 6d65 nit_array..comme
000006e0: 6e74 002e 6e6f 7465 2e47 4e55 2d73 7461 nt..note.GNU-sta
000006f0: 636b 002e 7265 6c61 2e65 685f 6672 616d ck..rela.eh_fram
00000700: 6500 0000 0000 0000 0000 0000 0000 0000 e...............
00000710: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000720: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000730: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000740: 0000 0000 0000 0000 2000 0000 0100 0000 ........ .......
00000750: 0600 0000 0000 0000 0000 0000 0000 0000 ................
00000760: 4000 0000 0000 0000 9100 0000 0000 0000 @...............
00000770: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000780: 0000 0000 0000 0000 1b00 0000 0400 0000 ................
00000790: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
000007a0: 2805 0000 0000 0000 0801 0000 0000 0000 (...............
000007b0: 0c00 0000 0100 0000 0800 0000 0000 0000 ................
000007c0: 1800 0000 0000 0000 2600 0000 0100 0000 ........&.......
000007d0: 0300 0000 0000 0000 0000 0000 0000 0000 ................
000007e0: d100 0000 0000 0000 0000 0000 0000 0000 ................
000007f0: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000800: 0000 0000 0000 0000 2c00 0000 0800 0000 ........,.......
00000810: 0300 0000 0000 0000 0000 0000 0000 0000 ................
00000820: d100 0000 0000 0000 0100 0000 0000 0000 ................
00000830: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000840: 0000 0000 0000 0000 3100 0000 0100 0000 ........1.......
00000850: 0200 0000 0000 0000 0000 0000 0000 0000 ................
00000860: d100 0000 0000 0000 0e00 0000 0000 0000 ................
00000870: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000880: 0000 0000 0000 0000 3e00 0000 0e00 0000 ........>.......
00000890: 0300 0000 0000 0000 0000 0000 0000 0000 ................
000008a0: e000 0000 0000 0000 0800 0000 0000 0000 ................
000008b0: 0000 0000 0000 0000 0800 0000 0000 0000 ................
000008c0: 0800 0000 0000 0000 3900 0000 0400 0000 ........9.......
000008d0: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
000008e0: 3006 0000 0000 0000 1800 0000 0000 0000 0...............
000008f0: 0c00 0000 0600 0000 0800 0000 0000 0000 ................
00000900: 1800 0000 0000 0000 4a00 0000 0100 0000 ........J.......
00000910: 3000 0000 0000 0000 0000 0000 0000 0000 0...............
00000920: e800 0000 0000 0000 1b00 0000 0000 0000 ................
00000930: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000940: 0100 0000 0000 0000 5300 0000 0100 0000 ........S.......
00000950: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000960: 0301 0000 0000 0000 0000 0000 0000 0000 ................
00000970: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000980: 0000 0000 0000 0000 6800 0000 0100 0000 ........h.......
00000990: 0200 0000 0000 0000 0000 0000 0000 0000 ................
000009a0: 0801 0000 0000 0000 7800 0000 0000 0000 ........x.......
000009b0: 0000 0000 0000 0000 0800 0000 0000 0000 ................
000009c0: 0000 0000 0000 0000 6300 0000 0400 0000 ........c.......
000009d0: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
000009e0: 4806 0000 0000 0000 4800 0000 0000 0000 H.......H.......
000009f0: 0c00 0000 0a00 0000 0800 0000 0000 0000 ................
00000a00: 1800 0000 0000 0000 0100 0000 0200 0000 ................
00000a10: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000a20: 8001 0000 0000 0000 4002 0000 0000 0000 ........@.......
00000a30: 0d00 0000 0e00 0000 0800 0000 0000 0000 ................
00000a40: 1800 0000 0000 0000 0900 0000 0300 0000 ................
00000a50: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000a60: c003 0000 0000 0000 6401 0000 0000 0000 ........d.......
00000a70: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000a80: 0000 0000 0000 0000 1100 0000 0300 0000 ................
00000a90: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000aa0: 9006 0000 0000 0000 7200 0000 0000 0000 ........r.......
00000ab0: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000ac0: 0000 0000 0000 0000 ........
, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1493:
.size main, .-main
.type _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB1982:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq , %rsp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
cmpl , -4(%rbp)
jne .L5
cmpl 535, -8(%rbp)
jne .L5
leaq _ZStL8__ioinit(%rip), %rdi
call _ZNSt8ios_base4InitC1Ev@PLT
leaq __dso_handle(%rip), %rdx
leaq _ZStL8__ioinit(%rip), %rsi
movq _ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rax
movq %rax, %rdi
call __cxa_atexit@PLT
.L5:
nop
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1982:
.size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
.type _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB1983:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl 535, %esi
movl , %edi
call _Z41__static_initialization_and_destruction_0ii
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1983:
.size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I_main
.hidden __dso_handle
.ident "GCC: (GNU) 7.2.1 20171128"
.section .note.GNU-stack,"",@progbits
Binary output (Generated from assembly)This is the unlinked form (i.e. not yet fully populated with symbol locations) of the binary output generated via g++ -c
in hexadecimal form. I generated the hexadecimal representation using xxd
.
二进制输出(从汇编生成)这是通过g++ -c
十六进制形式生成的二进制输出的未链接形式(即尚未完全填充符号位置)。我使用xxd
.
package mytest;
public class Test {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
These instructions correspond to an x86_64 machine. If you're interested in following along and matching the op codes, you can look at this referenceor download the Intel manualfor completeness. Likewise, it is an ELFfile so you can observe that we see things we expect (i.e. starting magic number of 0x7f
, etc.).
这些指令对应于 x86_64 机器。如果您有兴趣遵循并匹配操作码,您可以查看此参考资料或下载英特尔手册以确保完整性。同样,它是一个ELF文件,因此您可以观察到我们看到了我们期望的东西(即起始幻数0x7f
等)。
In any case, once linked against the system (i.e. run g++ test.cpp
or g++ test.s
or g++ test.o
), this executable runs directly on top of your OS. There are no additional translation layers between this and the OS. Even so, the OS still does OS things like abstracting hardware interfaces, manage system resources, etc.
在任何情况下,一旦链接到系统(即运行g++ test.cpp
或g++ test.s
或g++ test.o
),该可执行文件将直接在您的操作系统上运行。这和操作系统之间没有额外的转换层。即便如此,操作系统仍然做操作系统的事情,比如抽象硬件接口、管理系统资源等。
Tying this back to the original question, the output binary will look very different on a windows machine (for the same C++ code). At the very least, on a windows machine you would expect to see the file in the Portable Executable (PE) formatwhich is distinctly not ELF.
将此与原始问题联系起来,输出二进制文件在 Windows 机器上看起来会有很大不同(对于相同的 C++ 代码)。至少,在 Windows 机器上,您希望看到明显不是 ELF的可移植可执行 (PE) 格式的文件。
This is unlike the following Java example which requires a JVM to run:
这与以下 Java 示例不同,后者需要 JVM 才能运行:
Java Source FileThis is placed in a file called Test.java
Java 源文件这被放置在一个名为Test.java
00000000: cafe babe 0000 0034 001d 0a00 0600 0f09 .......4........
00000010: 0010 0011 0800 120a 0013 0014 0700 1507 ................
00000020: 0016 0100 063c 696e 6974 3e01 0003 2829 .....<init>...()
00000030: 5601 0004 436f 6465 0100 0f4c 696e 654e V...Code...LineN
00000040: 756d 6265 7254 6162 6c65 0100 046d 6169 umberTable...mai
00000050: 6e01 0016 285b 4c6a 6176 612f 6c61 6e67 n...([Ljava/lang
00000060: 2f53 7472 696e 673b 2956 0100 0a53 6f75 /String;)V...Sou
00000070: 7263 6546 696c 6501 0009 5465 7374 2e6a rceFile...Test.j
00000080: 6176 610c 0007 0008 0700 170c 0018 0019 ava.............
00000090: 0100 0c48 656c 6c6f 2077 6f72 6c64 2107 ...Hello world!.
000000a0: 001a 0c00 1b00 1c01 000b 6d79 7465 7374 ..........mytest
000000b0: 2f54 6573 7401 0010 6a61 7661 2f6c 616e /Test...java/lan
000000c0: 672f 4f62 6a65 6374 0100 106a 6176 612f g/Object...java/
000000d0: 6c61 6e67 2f53 7973 7465 6d01 0003 6f75 lang/System...ou
000000e0: 7401 0015 4c6a 6176 612f 696f 2f50 7269 t...Ljava/io/Pri
000000f0: 6e74 5374 7265 616d 3b01 0013 6a61 7661 ntStream;...java
00000100: 2f69 6f2f 5072 696e 7453 7472 6561 6d01 /io/PrintStream.
00000110: 0007 7072 696e 746c 6e01 0015 284c 6a61 ..println...(Lja
00000120: 7661 2f6c 616e 672f 5374 7269 6e67 3b29 va/lang/String;)
00000130: 5600 2100 0500 0600 0000 0000 0200 0100 V.!.............
00000140: 0700 0800 0100 0900 0000 1d00 0100 0100 ................
00000150: 0000 052a b700 01b1 0000 0001 000a 0000 ...*............
00000160: 0006 0001 0000 0003 0009 000b 000c 0001 ................
00000170: 0009 0000 0025 0002 0001 0000 0009 b200 .....%..........
00000180: 0212 03b6 0004 b100 0000 0100 0a00 0000 ................
00000190: 0a00 0200 0000 0500 0800 0600 0100 0d00 ................
000001a0: 0000 0200 0e .....
Java Byte Code (Generated from Java Source)This is generated by running javac -d . Test.java
and running the output file (i.e. mytest/Test.class
) through xxd
Java Byte Code (Generated from Java Source)这是通过运行javac -d . Test.java
和运行输出文件(即mytest/Test.class
)生成的xxd
As one would expect, the byte code output starts with 0xCAFEBABE.
正如人们所料,字节码输出以 0xCAFEBABE 开头。
The critical distinction here, however, is that this code cannot be run directly. It is still a binary output, but it's not intended to be executed directly by the operating system. If you tried to run this without a JVM on your system, you would just get an error. However, this code can be run on anyoperating system that contains a compatibleJVM. The set of compatible JVM's depends on how you've set your source and target. By default, it's equivalent to the Java version you're using to compile. In this case, I used Java 8.
然而,这里的关键区别是此代码不能直接运行。它仍然是一个二进制输出,但它并不打算由操作系统直接执行。如果你试图在你的系统上没有 JVM 的情况下运行它,你只会得到一个错误。但是,此代码可以在包含兼容JVM 的任何操作系统上运行。一组兼容的 JVM 取决于您如何设置 source 和 target。默认情况下,它等同于您用于编译的 Java 版本。在这种情况下,我使用了 Java 8。
The way this works is that your JVM is compiled for each system specifically (similarly to the C++ example above) and translatesits binary Java byte code into something your system can now execute.
它的工作方式是,您的 JVM 是针对每个系统专门编译的(类似于上面的 C++ 示例),并将其二进制 Java 字节代码转换为您的系统现在可以执行的内容。
At the end of the day, there is no free lunch-- as DanielKO mentioned in the comments, the JVM is still a "platform" but it's one-level higher than the OS so it can seem a bit more portable. Eventually, somewhere along the way, the code must translate to instructions valid for your specific operating system family and CPU architecture. However, in the case of Java and the JVM, you only have to compile a single application(i.e. the JVM itself) for all system flavors. At that point, everything written on top of the JVM has system support "for free" so to speak (as long as your application is entirely written in Java and isn't using native interfaces, etc.).
归根结底,天下没有免费的午餐——正如 DanielKO 在评论中提到的,JVM 仍然是一个“平台”,但它比 OS 高一个级别,因此它看起来更易于移植。最终,在此过程中,代码必须转换为对您的特定操作系统系列和 CPU 架构有效的指令。但是,在 Java 和 JVM 的情况下,您只需为所有系统风格编译一个应用程序(即 JVM 本身)。那时,在 JVM 之上编写的所有内容都可以说是“免费”的系统支持(只要您的应用程序完全用 Java 编写并且不使用本机接口等)。
As I mentioned before, there are many caveats to this information :) This was a pretty straightforward example intended to illustrate what you might actually observe. That said, we didn't get into calling native code, using custom JVM agents, or anything else which may affect this answer slightly. In general, however, these more often fall into the category of "special cases" and you wouldn't often be using these things unless you understood why and (hopefully) their implications to portability.
正如我之前提到的,此信息有许多警告:) 这是一个非常简单的示例,旨在说明您可能实际观察到的内容。也就是说,我们没有进入调用本机代码、使用自定义 JVM 代理或其他任何可能对这个答案产生轻微影响的东西。然而,一般而言,这些通常属于“特殊情况”的范畴,除非您了解原因以及(希望)它们对可移植性的影响,否则您不会经常使用这些东西。
回答by Lubo Antonov
C++ is not platform dependent - in fact there is a standard that all vendors try to implement. What you mean is that the EXECUTABLE that is produced is platform dependent. That is because each OS has a different definition and requirements of what constitutes a valid executable file. Also, each OS has a different set of APIs used for implementing core services that need to be linked against by the C++ linker and compiler. But this has nothing to do with C++ as a language.
C++ 不依赖于平台——事实上,所有供应商都试图实现一个标准。您的意思是生成的 EXECUTABLE 依赖于平台。这是因为每个操作系统对构成有效可执行文件的内容都有不同的定义和要求。此外,每个操作系统都有一组不同的 API,用于实现需要由 C++ 链接器和编译器链接的核心服务。但这与 C++ 作为一种语言无关。
回答by lurker
What makes a language, such as C++, "platform independent" is that it doesn't rely upon language constructs that are heavily favored by a given CPU architecture. Assembly language, for example and in contrast, is quite specific to a CPU architecture and instruction set. The front-end of a C++ compiler (parsing and semantic analysis) can be the same or basically the same for any computing platform it's targeted for. However, there still needs to be a platform or CPU specific code generator (e.g., for x86, ARM, etc).
使诸如 C++ 之类的语言“独立于平台”的原因在于它不依赖于给定 CPU 体系结构非常青睐的语言结构。例如,相比之下,汇编语言非常特定于 CPU 架构和指令集。C++ 编译器的前端(解析和语义分析)对于它所针对的任何计算平台都可以相同或基本相同。但是,仍然需要一个平台或 CPU 特定的代码生成器(例如,用于 x86、ARM 等)。
An EXE is a binary file specifically compiled and code-generated for DOS/Windows platform. It's structure is known by the DOS/Windows system and it contains information for how to locate the executable in memory as well as all of the instruction codes specific to CPU/platform for it to run. As indicated by Oleksandr, its specific format can be found, for example, on Wikipedia.
EXE 是专门为 DOS/Windows 平台编译和代码生成的二进制文件。它的结构为 DOS/Windows 系统所知,它包含有关如何在内存中定位可执行文件的信息以及特定于 CPU/平台运行的所有指令代码。正如 Oleksandr 所指出的,它的具体格式可以在例如 Wikipedia 上找到。
回答by Ramesh Karna
Actually C++ is not a platform dependent, but the output it produces is in .exe or other format which is depend on the platform you are using. so simply C++'s code is independent of platform, just the output comes after compilation is dependent.
实际上 C++ 不依赖于平台,但它产生的输出是 .exe 或其他格式,这取决于您使用的平台。所以简单地说,C++ 的代码是独立于平台的,只是编译后的输出是相关的。
回答by Kent
C++ is not platform dependent per se, but it is possible to write platform dependent code with C++ by calling Windows and/or Linux only APIs. It is also possible to be locked to a particular platform if you use Microsoft-only C++ extensions etc.
C++ 本身并不依赖于平台,但可以通过调用 Windows 和/或 Linux 的 API 来使用 C++ 编写平台相关的代码。如果您使用仅限 Microsoft 的 C++ 扩展等,也可能被锁定到特定平台。
The executable format for a given platform is a whole different league.
给定平台的可执行格式是一个完全不同的联盟。
回答by Thomas Matthews
C++ is not platform dependent.
C++ 不依赖于平台。
There are other platforms out there besides Windows.
除了Windows,还有其他平台。
There are other processors out there besides the X86 or Pentium that Windows runs on.
除了运行 Windows 的 X86 或 Pentium 之外,还有其他处理器。
The is an area called "Embedded Systems" which uses the C++ language on many other kinds and brands of operating systems and processors. For example, there are DSPs, the good old 8051 and the ARM series.
这是一个称为“嵌入式系统”的领域,它在许多其他种类和品牌的操作系统和处理器上使用 C++ 语言。例如,有 DSP、老式的 8051 和 ARM 系列。
The reason high level languages were invented is so that a program can be written once but compiled (translated) to other platforms. For example, a platform independent C++ program can be compiled for a PDP machine, Windows, Mac, Unix, Vrtx, Windriver, ARM processor, all without changing the program.
发明高级语言的原因是程序可以编写一次,但可以编译(翻译)到其他平台。例如,可以为PDP机器、Windows、Mac、Unix、Vrtx、Windriver、ARM处理器编译一个平台无关的C++程序,而无需更改程序。
In general executables are platform dependent.
一般来说,可执行文件是平台相关的。
回答by David K
There are two important aspects to any programming language (such as C++) that this question touches upon:
这个问题涉及任何编程语言(例如 C++)的两个重要方面:
- How you tell the computer to do what you want.
- How the computer does what you told it to.
- 你如何告诉计算机做你想做的事。
- 计算机如何执行您告诉它的操作。
The second aspect will alwaysbe platform-dependent, because the computer must use the machine codes, system libraries, and so forth that work on the particular processor architecture and operating system of that computer.
第二个方面将始终是平台相关的,因为计算机必须使用机器代码、系统库等,它们适用于该计算机的特定处理器体系结构和操作系统。
The first aspect may or may not be platform-dependent, depending on the language and how you use it.
第一个方面可能依赖于平台,也可能不依赖于平台,具体取决于语言和您使用它的方式。
So a *.exe file is a platform-dependent thing, because it says exactly how the computer will do what you told it to do. But the *.exe file is not C++; it could have been compiled from some other programming language.
所以 *.exe 文件是一个平台相关的东西,因为它准确地说明了计算机将如何做你告诉它做的事情。但是 *.exe 文件不是 C++;它可能是从某种其他编程语言编译而来的。
A C++ program may or may not be platform-dependent. If you call functions that are provided by the compiler on Windows and not in other operating systems, then your C++ program will compile only on Windows. That is a platform dependence. But if you avoid calling platform-dependent functions such as those, you can compile the C++ program anywhere.
C++ 程序可能依赖于平台,也可能不依赖于平台。如果您在 Windows 上调用由编译器提供的函数,而不是在其他操作系统中,那么您的 C++ 程序将只能在 Windows 上编译。那就是平台依赖。但是如果你避免调用这些平台相关的函数,你就可以在任何地方编译 C++ 程序。