用C语言编译后生成的可执行文件是否可以复制并在任何不同的操作系统(UNIX)上运行?

用C语言编译后生成的可执行文件是否可以复制并在任何不同的操作系统(UNIX)上运行?,c,C,我是一名java程序员,但我在C语言中几乎没有什么事情要做。因此,我从下面的一个简单示例开始。如果我已经编译并生成了一个可执行文件(hello),那么我可以在任何unix平台上运行该可执行文件(hello),而不使用原始文件(hello.c)?还有从可执行文件中读取数据的方法吗?就是说,将可执行文件反编译为原始文件(hello.c) 不。。。每个平台可能有不同的可执行文件格式要求、不同的硬件架构、由链接器确定的不同可执行内存布局等。已编译的可执行文件是其当前编译平台的“本机”,而不是其他平台。不

我是一名java程序员,但我在C语言中几乎没有什么事情要做。因此,我从下面的一个简单示例开始。如果我已经编译并生成了一个可执行文件(hello),那么我可以在任何unix平台上运行该可执行文件(hello),而不使用原始文件(hello.c)?还有从可执行文件中读取数据的方法吗?就是说,将可执行文件反编译为原始文件(hello.c)


不。。。每个平台可能有不同的可执行文件格式要求、不同的硬件架构、由链接器确定的不同可执行内存布局等。已编译的可执行文件是其当前编译平台的“本机”,而不是其他平台。不过,您可以在当前计算机上交叉编译另一个体系结构


例如,尽管它们可能有许多相似之处,但Linux x86上编译的可执行文件不一定能在BSD下运行,这取决于它的风格(即,您可能会在FreeBSD下运行它,但通常不会在OSX达尔文版本的BSD下运行,甚至认为这两台机器可能具有相同的底层硬件体系结构)。您也无法在运行IRIX的SGI MIPS计算机上编译某些内容,并在运行Solaris的Sun SPARC上运行。

您无法在任何平台上运行可执行文件

您可以在其他机器(或这台机器)上运行该可执行文件,而无需.c文件。如果是在同一硬件上运行的同一操作系统/发行版


您可以使用反编译器反汇编程序来读取文件并将其作为汇编或C进行查看——它们看起来与原始C文件不太像。

对于C程序,程序与编译它的环境相关联(通常与编译它的平台相同,除非您是交叉编译)。您可以将为一个版本的Linux(以及特定的硬件体系结构)构建的东西复制到另一台运行相同版本Linux的具有相同体系结构的机器上,这样就可以了。您通常可以在相关版本的Linux上运行它。但您无法在IA32机器、PPC机器或SPARCmachine上运行x86/64代码。如果基本的O/S足够相似,那么很可能可以在x86/64机器上运行IA32代码。您可能会也可能无法获得一些编译后的东西,以便Debian在RedHat下运行,反之亦然;这取决于程序使用的库


Java通过编译与平台无关的字节码程序和在每个平台上运行特定于平台的JVM(JRE)来避免这种情况。这种蠕虫(一次写入,多次运行)行为是Java的一个关键卖点。

编译的文件是纯机器代码(加上一些元数据),因此它是自给自足的,因为它不需要提供源文件。缺点是什么?机器代码是特定于操作系统和平台的。所谓平台,我们通常只是粗略地指CPU的指令集,即“x86”或“PowerPC”,但使用某些编译器标志编译的某些代码可能需要特定的指令集扩展。操作系统依赖性不仅是由可执行文件的不同格式(例如ELF而不是PE)引起的,而且也是由使用操作系统特定的服务或以操作系统特定的方式使用通用操作系统服务(例如系统调用)引起的。除此之外,几乎所有的非平凡代码都依赖于某些库(至少是一个C运行时库),因此如果没有兼容版本中正确的库,您可能无法运行可执行文件。因此,不,您的可执行文件可能不会在已有10年历史的专有UNIX上运行,也可能不会在不同的Linux发行版上运行(尽管您的程序很有可能会运行,因为它可能只依赖于
glibc


虽然机器代码可以很容易地反汇编,但其结果是非常低级的,对许多人来说是无用的。反编译到C几乎总是困难得多,尽管有尝试。算法可以恢复,只是因为它们必须以某种方式编码到机器代码中。假设您没有为调试而编译,它将永远不会恢复注释、格式、变量名等。因此,即使是“完美”的反编译器也会生成与您输入的C文件不同的C文件。

您可以在与编译可执行文件的平台ABI兼容的平台上运行生成的可执行文件。ABI兼容性基本上意味着在两个(可能不同的)操作系统上使用相同的物理处理器体系结构和操作系统接口(加上调用约定)。例如,您可以在FreeBSD系统上运行为Linux编译的二进制文件(使用相同的处理器类型),因为FreeBSD包含Linux ABI兼容性。然而,除非进行了黑客攻击,否则可能无法在所有其他类型的Unice上运行二进制文件。例如,您不能在linux上运行Mac OS X应用程序,但是,有了它,您就可以在linux上使用一些OS X命令行工具(包括GCC编译器本身)

逆向工程:确实有反编译器,其目的是从机器代码生成C代码,但它们(还)不是很强大。原因是它们天生就很难写。必须识别机器代码模式,即使这样,也无法收集所有原始信息。例如,循环类型、注释和非静态局部变量名以及大多数类型在编译过程中都消失了。例如,如果您有如下C源文件:

int main(int argc, char **argv)
{
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("I is: %d\n", i); /* Write the value of I */
    }

    return 0;
}
int main(int argc,char**argv)
{
int i;
对于(i=0;i<10;i++)
{
printf(“I是:%d\n”,I);/*写入I的值*/
}
返回0;
}
C反编译器可能能够重建以下代码:

int main(int _var1, void *_var2)
{
    int _var3 = 0;
    while (_var3 < 10)
    {
        printf("I is: %d\n", _var3);
        _var3 = _var3 + 1;
    }

    return 0;
}
int-main(int-var1,void*\u-var2)
{
int_var3=0;
而(_var3<10)
{
printf(“I是:%d\n”,\u var3);
_var3=_var3+1;
}
返回0;
}
但这将是一个相当高级的反编译器,例如

是的,您可以在任何计算机上运行它
int main(int argc, char **argv)
{
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("I is: %d\n", i); /* Write the value of I */
    }

    return 0;
}
int main(int _var1, void *_var2)
{
    int _var3 = 0;
    while (_var3 < 10)
    {
        printf("I is: %d\n", _var3);
        _var3 = _var3 + 1;
    }

    return 0;
}