C维基书籍 - C如何成为“你所看到的就是所有你得到的”语言?

时间:2017-06-02 11:23:35

标签: c

我无法理解 WikiBooks 中的以下句子之一:

为什么是C,而不是汇编语言?

  

“C是一种编译语言,可以创建快速有效的可执行文件。它也是一个小的”你看到的就是所有你得到的“语言:一个C语句最多只对应一些汇编语句,其他一切都是由图书馆职能部门提供。“

网站链接 C Programming/Why learn C? - Wikibooks, open books for an open world

注意:我是一个完全的初学者,我已经开始学习C语言了。所以,我需要对上述句子的含义进行精确解释。

7 个答案:

答案 0 :(得分:7)

程序集是单个处理器系列的语言,它直接编译为处理器运行的机器代码。如果汇编中有一个程序,则需要为不同的处理器系列重写整个代码。手机通常使用ARM处理器,而台式计算机则使用32位或64位x86兼容处理器。其中3个可能需要一个完全独立编写的程序,甚至可能不限于此。

相比之下,标准C是一种可移植的语言 - 如果您编写所谓的严格符合程序。 C11 4p5

  

严格遵守的程序应仅使用本国际标准中规定的语言和库的特征。 (3)它不应产生依赖于任何未指定,未定义或实现定义的行为的输出,并且不得超过任何最小实现限制。

footnote 5注意到:

  

严格符合的程序旨在最大程度地在符合要求的实现中可移植。合规程序可能依赖于符合实现的不可移植特征

与处理器的细节因处理器而异的汇编程序不同,可以用C语言编写程序,然后将 port 编写到各种平台而不需要对源代码进行任何更改,但这些程序仍然是编译成汇编语言,在使用现代高质量优化编译器时,性能可以 - 而且经常会 - 超过手写汇编。

此外,任何符合托管实现需要提供的 C标准库都提供了一种可移植的方式来管理文件,动态内存,输入和输出,所有这些都不仅是处理器而且还是处理器使用汇编程序时特定于操作系统。

但是,C仍然非常接近程序集,因为它被某些人称为“高级汇编语言”。

答案 1 :(得分:3)

compiled languageinterpreted language是没有意义的。

这种陈述是由没有受过教育的人做出的,无法理解编程的基础。

语言是通过定义语言的方式在数学上定义的 - 操作,指称,公理等,程序员可以按照自己的意愿实现语言。

有些机器通过解释运行C,它们在执行时调度代码并执行它而不是累积一些稍后由某些机器执行的目标代码等。

compiled implementationinterpreted implementation for the language是正确的,但即便如此,它也与给定的机器有关。因为当你为x86处理器compile时,编译的代码由堆栈机器的数据路径和控制器解释为X86语言等。

基本上,语句what you see is all you get意味着在ISO 9899的抽象语义中定义的CAM运算符与市场上当前的堆栈机器(如x86,mips等)之间几乎是1对1的对应关系。

答案 2 :(得分:2)

C只不过是一个独立于平台的汇编翻译器,你在C中编写的内容被有效地“翻译”成机器代码,就像你直接在Assembly中编写它一样。这就是:

  

“你看到的就是你所得到的”语言:C语句最多只能对应少数汇编语句

与其他语言不同,编写的任何C语句都由编译器直接转换为ASM,没有抽象层,解释器等。

根据定义,C是微不足道的,它只有被认为是turing complete语言的东西,仅此而已。任何附加功能都是通过库实现的,C提供了包含RNG,内存管理等功能的std lib(不同的实现)。

这就是这个意思:

  

其他一切都由库函数提供

答案 3 :(得分:2)

关于C,这是一个陈旧且过时的说法。

C最初被设计为粗略的,更易读和便携的汇编程序。出于这个原因,大多数核心语言功能(在大多数目标机器上)都很容易翻译。通常,库函数提供了更复杂的功能,包括标准库。

随着时间的推移,C(语言和标准库)都在不断发展,变得更加复杂。计算硬件也变得更加复杂 - 例如,支持一组更高级的指令 - 并且可以用高级指令实现的C结构将转换为支持更旧和更简单指令集的机器上更复杂的汇编程序。

“小”语言和“大”语言之间的区别是完全主观的 - 所以有些人仍然继续将C描述为小而简单,其他人描述的同样大而复杂。虽然比其他一些语言(如C ++)更简单,但现在通过各种措施,C也比其他一些编程语言复杂得多。

答案 4 :(得分:2)

这句话绝对适用于70'的良好旧K& R C实施。在过去,C确实是机器指令的薄包装,程序员可以轻松猜出编译器如何翻译源代码:

  • for循环:适当寄存器中的计数器,循环结束时的测试goto
  • 函数调用:将参数推送到堆栈(没有转换!),调用子例程地址。返回时将返回值(需要是标量或指针)放到适当的寄存器中并使用机器返回。返回时,调用者清理堆栈

在对称的观点上,处理器可以执行的任何事情都可以用C表示。如果你有一个包含两个整数的数组,并且知道内部表示是一个有效的double,那么只需转换一个指针并使用它

最新版本的C语言和优化编译器都错了。 好像规则允许优化器执行任何操作,如果可观察的结果是自然实现应该给出的。许多操作都可以调用未定义的行为。例如,在存储器位置写入一个浮点并将其用作整数是明确的UB。优化器可以假设程序中不存在UB,因此它可以优化掉任何包含UB的块(最近版本的gcc非常好)。

查看此功能的示例:

void stopit() {
   int i = 0;
   while(1) {
      i+=1;
   }
   printf("done");
}

它包含一个无限循环,因此永远不会到达printf。但是循环没有可观察到的结果,因此编译器可以自由地优化它并将其翻译为:

void stopit() {
   printf("done");
}

另一个例子

int i = 12;
float *f = &i;
*f = 12.5;              // UB use an float variable to access an int
printf("0x%04x\n", i);  // try to dump the representation of 12.5

此代码可合法显示0x000c,因为编译器可以自由地假设*f=0.未修改i,因此它可以直接使用缓存值并转换最后一行直接作为printf("0x%04x\n", 12);

所以不是,C语言的最新版本不再是一个小的"你看到的就是你得到的所有#34;语言

真实的是C是一种低级语言。程序员可以完全控制动态存储的分配/释放。对于任何类型,您都可以在字节级别进行自然访问,您可以使用指针和显式指针/整数转换的概念,以允许直接访问众所周知的内存地址。这确实允许在C中编程嵌入式系统或微控制器。该标准甚至定义了两个环境级别:一个托管环境,您可以完全访问标准库,以及一个不存在标准库的独立环境。对于内存很少的系统,这可能特别有趣。

答案 5 :(得分:1)

C在字节和位级别提供对存储器和资源的低级控制。例如,C和汇编语言在微控制器(我的专业领域)的编程中非常常见,它们具有非常少的存储器并且通常需要对输入和输出端口进行位级控制。

如果您编写C程序并构建它,那么查看您的列表文件,您通常会看到C语句与C组装的少数汇编指令之间非常接近的对应关系。

其简单性的另一个线索是查看其语法定义,例如与C#或Java或Python相比。与“更完整”相比,C语法小巧,简洁,紧凑。语言,而且确实如此,在C中定义的输入或输出甚至没有。这通常来自包括stdio.h或类似的。通过这种方式,您只能获得可执行文件中所需的内容。这与" big"开始形成鲜明对比。语言。

虽然嵌入式(微控制器)编程空间中的许多人仍然喜欢组装,但C是一种很好的方法来抽象控制和指针流等一点点之类的东西,同时仍然保留了实际应用的能力微处理器或微控制器能够执行的每条指令。

答案 6 :(得分:0)

关于"你看到的是你得到的所有"声明...

C是"小"语言只提供少数抽象 - 也就是说,隐藏特定于实现的细节(如I / O,类型表示,地址表示等)或简化的高级语言结构复杂的操作(内存管理,事件处理等)。 C不提供语言级别(语法或标准库)中的任何支持,如网络,图形,声音等;您必须为这些任务使用单独的第三方库,这些库将根据平台(Windows,MacOS,iOS,Linux)而有所不同。将它与Java这样的语言进行比较,Java提供了一个类库,可以提供您想要做的所有所有的类库。

与C ++和Java等语言相比,并没有发生很多事情。#34;引擎盖下#34;在C.没有函数或运算符的重载,没有在创建或销毁对象时自动调用的构造函数或析构函数,并且没有真正支持" generic"编程(编写可以为不同类型的参数自动实例化的函数模板)等。因此,通常更容易预测特定代码片段的执行方式。

C中没有自动资源管理 - 当您添加或删除元素时,数组不会增长或缩小,没有自动垃圾回收功能可以回收动态内存,而您不会这样做。再使用等等。

C语言提供的唯一容器是数组 - 对于任何更复杂的(列表,树,队列,堆栈等),您必须编写自己的实现,或使用其他人的库。

C"靠近机器"因为它提供的类型和抽象基于真实世界的硬件提供。例如,整数和浮点表示和操作基于本机硬件支持的内容。 int的大小(通常)基于本机CPU的字大小,这意味着它只能表示一定范围的值(语言标准所需的最小范围为[-32767..32767]对于有符号整数,对于无符号整数,[0..65535]int对象上的操作映射到本机ADD/DIV/MUL/SUB操作码。 Python之类的语言提供了"任意精度"类型,不受硬件本身支持的限制 - 权衡是使用这些类型的操作通常较慢,因为您不使用本机操作码。