知道命令式编程和声明式编程之间的区别是非常令人困惑的,任何人都可以用现实世界的术语来解释两者之间的区别吗?
请澄清 C 是命令式语言还是声明式语言?
知道命令式编程和声明式编程之间的区别是非常令人困惑的,任何人都可以用现实世界的术语来解释两者之间的区别吗?
请澄清 C 是命令式语言还是声明式语言?
C 是一种命令式编程语言。
两者之间的一条区别是声明式编程是当你说出你想要的东西时,而命令式编程是当你说出如何得到你想要的东西时。在声明式编程中,重点是计算机应该做什么而不是它应该如何做(例如 SQL),而在命令式编程中,重点是计算机应该采取什么步骤而不是计算机将做什么(例如 C 、C++、Java)。
命令式编程是一种编程范式,它根据改变程序状态的语句来描述计算
声明式编程是一种编程范式,一种构建计算机程序结构和元素的风格,它表达了计算的逻辑而不描述其控制流
许多命令式编程语言(例如 Fortran、BASIC 和 C)是汇编语言的抽象。
维基说: -
作为一种命令式语言,C 使用语句来指定动作。最常见的语句是表达式语句,由要计算的表达式和分号组成;作为评估的副作用,可以调用函数并且可以为变量分配新值。为了修改语句的正常顺序执行,C 提供了几个由保留关键字标识的控制流语句。if(-else) 条件执行、do-while、while 和迭代执行(循环)支持结构化编程。for 语句具有单独的初始化、测试和重新初始化表达式,其中任何一个或全部都可以省略。break 和 continue 可用于离开最里面的封闭循环语句或跳至其重新初始化。还有一个非结构化 goto 语句直接分支到函数内的指定标签。switch 根据整数表达式的值选择要执行的案例。
警告
我写了很多笼统的东西,所以请多多包涵。
理论上
C 是命令式的,因为代码读起来就像是如何做某事的秘诀。但是,如果您使用大量命名良好的函数和函数指针来实现多态性,则可以使 C 代码看起来像一种声明性语言。
在命令式语言中,您专注于算法/实现。工程本质上是必不可少的,因为您专注于流程的效率:在时间或金钱(或 CS 中的内存)方面做某事的成本。
相比之下,数学通常是陈述性的(但写一个证明往往更加必要)。在数学中,你更关心正确性和定义不变的关系/操作,而不是你能多快得到答案。
请注意,许多函数式语言本质上倾向于声明性(例如 R、Lisp)。
z = x + y 是什么意思?(语义)
在命令式语言中,这意味着从内存位置 x 和 y 读取,将这些值相加,然后将结果放入内存位置 z,然后立即执行。如果为 x 分配不同的值,则必须再次使用该z = x + y
语句来重新计算 z。
在声明性(惰性)语言中,这意味着 z 是一个变量,其值是其他两个变量 x 和 y 的值之和。在您尝试读取 z 的值之前,不会执行加法运算。有什么含义?如果您从 z 中读取,该值将始终是该时刻 x 和 y 的总和;您无需重新发出声明。在没有变量的纯声明性语言中,重新发布实际上可以被捕获为错误!!!
记住这个例子,你就会明白为什么数学家更喜欢声明性语言。例如,我可以定义 hypotenuse = sqrt( height^2 + length^2 ) 而不必担心必须重新发出该语句。这种关系是一个永远成立的不变量,就像一个数学真理永远成立一样。
在现实生活中(我为什么要关心?)
声明式语言的支持者声称:错误(错误)的有效解决方案是无用的。他们想要没有错误、无状态的函数,没有副作用,可以在不修改的情况下重复使用。
命令式语言的支持者声称:一个需要永远运行的正确解决方案也是无用的。他们希望控制内存/速度的权衡。他们希望能够根据物理和时间限制进行优化。
当然,没有什么是 100% 的命令式或声明式的。 正确且编写良好的命令式代码暗示了某些关系。OTOH,声明性代码,足够深入并与语言规范相结合,足以很好地描述这些关系,以便编译器/解释器将您的代码转换为一系列 CPU 指令。
因为我们正在处理计算机,所以声明式编译器/解释器必须足够聪明,以便在时间与内存之间进行权衡,而在命令式语言中,由程序员更明确地做出这些决定。
因此,声明性语言要求程序员专注于定义变量和其他不变量之间的关系。由编译器/解释器将这些关系转换为 CPU 的一系列指令/操作。大多数声明式编译器/解释器足够聪明,可以处理大多数实际情况,但可能会遇到边缘情况。不幸的是,在这些情况下,您将不得不哄骗编译器/解释器。
哪一个更好?
声明式语言的支持者声称,此类语言允许程序员专注于领域并编写非程序员更容易阅读的代码。倡导者声称,编写正确的代码更容易。然而,权衡是,哄骗编译器/解释器做出正确的内存与速度权衡可能需要一些复杂的语言知识。如果您使用像 R 或 SQL 或 LISP 这样的声明性语言,您将理解这个问题。当然可以定义一种与计算机无关的新声明性语言(但这样做可能会使解释器/编译器的编写者更难)。许多数学家和纯 CS 研究人员喜欢声明性语言。
命令式语言倾向于让您对机器进行更细粒度的控制。毫无疑问,您正在对计算机进行编程。陷阱是,我们最终可能会过早地关注那些损害代码维护和可读性的不必要的速度优化。在速度或内存严重受限的计算早期,您需要使用命令式语言来完成有用的工作,并针对您的情况进行正确优化。工程师和修补匠倾向于使用命令式语言。
C 是一种命令式语言。
命令式语言指定如何做你想做的事。声明性语言指定你想要什么,而不是如何去做;语言解决了如何做到这一点。Prolog 是声明性语言的一个例子。
我想评论一下,在没有明确规则的情况下,C 语言的某些方面是声明性的……
int i = 4;
int j = 5;
float f = i/j;
似乎意味着您打算将浮点数设为 .80(并且在声明性语言中,它很可能是)......但是由于有明确定义的过程 int/int 使用整数除法计算为 int (在 C 中是楼层划分)。
正是显式定义的行为使得 C 势在必行。
C 底层有一个秘密可以进行优化,只要它们保证不改变程序的输出,这使得编译器具有一些声明性行为,其中声明是输入 C 程序的行为,但最终结果可以是任何与该 C 程序在功能上相匹配的东西
§5.1.2.3 第 10 部分:
或者,实现可能会在每个翻译单元内执行各种优化,以便实际语义只有在跨翻译单元边界进行函数调用时才会与抽象语义一致。在这样的实现中,在调用函数和被调用函数在不同的翻译单元中的每个函数入口和函数返回时,所有外部链接对象的值以及通过其中的指针可访问的所有对象的值将符合抽象语义. 此外,在每个这样的函数进入时,被调用函数的参数值以及通过其中的指针可访问的所有对象的值将与抽象语义一致。在这种类型的实现中,
以及下一部分的具体示例:
示例 2 在执行片段时
char c1, c2; /* ... */
c1 = c1 + c2;
“整数提升”要求抽象机将每个变量的值提升为整数大小,然后将两个整数相加并截断总和。如果添加两个字符可以在没有溢出的情况下完成,或者溢出包装静默产生正确的结果,实际执行只需要产生相同的结果,可能会省略促销。
-> 命令式编程:告诉“机器”如何做某事,结果你想要发生的事情就会发生。
-> 声明式编程:告诉“机器”你想发生什么,让计算机弄清楚如何去做。
所以我们可以说 C 是一种命令式语言。