我问的是关于 c# 的问题,但我认为它在大多数其他语言中都是一样的。

有谁有一个好的定义 表达式声明 区别是什么?

有帮助吗?

解决方案

表达: 评估某个值的东西。例子: 1+2/x
陈述: 执行某事的一行代码。例子: 转到 100

在最早的通用编程语言(如 FORTRAN)中,区别是非常明显的。在 FORTRAN 中,语句是一个执行单元,是您所做的一件事情。它不被称为“线”的唯一原因是因为有时它跨越多条线。光靠表情是起不了任何作用的……你必须将它分配给一个变量。

1 + 2 / X

在 FORTRAN 中是一个错误,因为它不执行任何操作。你必须对这个表达式做一些事情:

X = 1 + 2 / X

FORTRAN 并没有我们今天所知的语法——这个想法是与巴科斯-诺尔范式 (BNF) 一起发明的,作为 Algol-60 定义的一部分。那时 语义 区分(“具有价值”与“做某事”)被铭记于心 句法: :一种短语是表达式,另一种是语句,解析器可以区分它们。

后来语言的设计者模糊了区别:它们允许句法表达式做事,并且允许具有值的句法语句。仍然存在的最早的流行语言示例是 C。C 的设计者意识到,如果允许计算表达式并丢弃结果,则不会造成任何损害。在 C 中,每个语法表达式都可以通过在末尾添加分号来构成语句:

1 + 2 / x;

这是一个完全合法的声明,即使绝对不会发生任何事情。类似地,在 C 中,表达式可以具有 副作用——它可以改变一些东西。

1 + 2 / callfunc(12);

因为 callfunc 可能只是做一些有用的事情。

一旦允许任何表达式成为语句,您也可以允许在表达式内使用赋值运算符 (=)。这就是为什么 C 让你做类似的事情

callfunc(x = 2);

这会计算表达式 x = 2(将 2 的值分配给 x),然后将其(2)传递给函数 callfunc.

这种表达式和语句的模糊现象出现在所有 C 派生语言(C、C++、C# 和 Java)中,它们仍然有一些语句(例如 while)但它允许几乎任何表达式用作语句(在 C# 中,只有赋值、调用、递增和递减表达式可以用作语句;看 斯科特·维斯涅夫斯基的回答).

拥有两个“句法类别”(这是语句和表达式所属类别的技术名称)可能会导致重复工作。例如,C有两种形式的条件,语句形式

if (E) S1; else S2;

以及表达形式

E ? E1 : E2

有时人们 不存在的重复:例如,在标准C中,只有一个语句才能声明新的局部变量,但是此功能足够有用,以使GNU C编译器提供了GNU扩展程序,使表达式也可以声明局部变量。

其他语言的设计者不喜欢这种重复,他们很早就看到,如果表达式可以像值一样具有副作用,那么 句法的 语句和表达式之间的区别并不是那么有用——所以他们放弃了它。Haskell、Icon、Lisp 和 ML 都是没有句法语句的语言,它们只有表达式。甚至类结构化循环和条件形式也被视为表达式,并且它们具有值,但不是非常有趣的值。

其他提示

我想对乔尔上面的回答做一个小小的修正。

C# 不允许所有表达式都用作语句。特别是,只有赋值、调用、递增和递减表达式可以用作语句。

例如,C# 编译器会将以下代码标记为语法错误:

1 + 2;

  • 表达式是任何能产生值的东西:2+2
  • 语句是程序执行的基本“块”之一。

请注意,在 C 语言中,“=”实际上是一个运算符,它有两件事:

  • 返回右侧子表达式的值。
  • 将右侧子表达式的值复制到左侧的变量中。

以下是 ANSI C 语法的摘录。你可以看到 C 没有很多不同种类的语句......程序中的大多数语句都是表达式语句,即末尾带有分号的表达式。

statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html

表达式是返回值的东西,而语句则不返回值。

举些例子:

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

两者之间的重要之处在于您可以将表达式链接在一起,而语句则不能链接在一起。

您可以在 维基百科, ,但表达式会计算为某个值,而语句则没有计算值。

因此,表达式可以在语句中使用,但反之则不行。

请注意,某些语言(例如 Lisp,我相信 Ruby,以及许多其他语言)不区分语句与表达式...在这样的语言中,一切都是一个表达式,并且可以与其他表达式链接。

为了解释表达式与语句的可组合性(可链接性)的重要差异,我最喜欢的参考文献是约翰·巴克斯的图灵奖论文, 编程能否从冯诺依曼风格中解放出来?.

命令式语言(Fortran、C、Java 等)强调用于构造程序的语句,并使用表达式作为一种事后思考。函数式语言强调表达式。 纯粹 函数式语言具有如此强大的表达式,以至于可以完全消除语句。

简单地:表达式计算出一个值,而语句则不然。

可以计算表达式来获取值,而语句不返回值(它们的类型 空白).

函数调用表达式当然也可以被认为是语句,但是除非执行环境有一个特殊的内置变量来保存返回值,否则无法检索它。

面向语句的语言要求所有过程都是语句列表。面向表达式的语言(可能都是函数式语言)是表达式列表,或者在 LISP 的情况下,是一个代表表达式列表的长 S 表达式。

尽管两种类型都可以组合,但只要类型匹配,大多数表达式都可以任意组合。每种类型的语句都有自己的编写其他语句的方式(如果它们都能做到的话)。Foreach 和 if 语句需要单个语句,或者所有从属语句一个接一个地进入一个语句块,除非子语句允许它们自己的子语句。

语句还可以包含表达式,其中表达式实际上并不包含任何语句。不过,一个例外是 lambda 表达式,它代表一个函数,因此可以包含函数可以包含的任何内容,除非该语言仅允许有限的 lambda,例如 Python 的单表达式 lambda。

在基于表达式的语言中,您所需要的只是函数的单个表达式,因为所有控制结构都返回一个值(其中许多控制结构返回 NIL)。不需要 return 语句,因为函数中最后计算的表达式就是返回值。

关于基于表达式的语言的一些事情:


最重要的:一切都有返回值


用于分隔代码块和表达式的大括号和大括号没有区别,因为一切都是表达式。但这并不能阻止词法作用域:例如,可以为包含其定义的表达式以及其中包含的所有语句定义局部变量。


在基于表达式的语言中,一切都会返回一个值。一开始这可能有点奇怪——什么是 (FOR i = 1 TO 10 DO (print i)) 返回?

一些简单的例子:

  • (1) 回报 1
  • (1 + 1) 回报 2
  • (1 == 1) 回报 TRUE
  • (1 == 2) 回报 FALSE
  • (IF 1 == 1 THEN 10 ELSE 5) 回报 10
  • (IF 1 == 2 THEN 10 ELSE 5) 回报 5

几个更复杂的例子:

  • 有些东西,例如某些函数调用,实际上并没有返回有意义的值(只会产生副作用的东西?)。呼唤 OpenADoor(), FlushTheToilet() 或者 TwiddleYourThumbs() 将返回某种普通值,例如“OK”、“Done”或“Success”。
  • 当在一个较大的表达式中计算多个未链接的表达式时,大表达式中计算的最后一个值将成为该大表达式的值。举个例子 (FOR i = 1 TO 10 DO (print i)), ,for循环的值为“10”,它导致 (print i) 要计算 10 次的表达式,每次都将 i 作为字符串返回。最后一次通过返回时间 10, ,我们的最终答案

通常需要稍微改变思维方式才能充分利用基于表达式的语言,因为一切都是表达式这一事实使得“内联”很多东西成为可能

举个简单的例子:

 FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO
 (
    LotsOfCode
 )

是非基于表达式的完全有效的替代

IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 
FOR i = 1 TO TempVar DO
(    
    LotsOfCode  
)

在某些情况下,基于表达式的代码允许的布局对我来说感觉更自然

当然,这可能会导致疯狂。作为基于表达式的脚本语言 MaxScript 的爱好项目的一部分,我设法想出了这个怪物系列

IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO
(
    LotsOfCode
)

语句是表达式的一种特殊情况,其中包含 void 类型。语言以不同方式对待语句的倾向经常会引起问题,如果能适当地概括它们会更好。

例如,在 C# 中,我们有非常有用的 Func<T1, T2, T3, TResult> 通用委托的重载集。但我们也得有相应的 Action<T1, T2, T3> 也设置了,并且必须不断地重复通用高阶编程来处理这种不幸的分叉。

简单的示例 - 在调用另一个函数之前检查引用是否为 null 的函数:

TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
                  where TValue : class
{
    return (value == null) ? default(TValue) : func(value);
}

编译器可以处理这种可能性吗 TResult 存在 void?是的。它所要做的就是要求 return 后跟一个类型的表达式 void. 。的结果 default(void) 将是类型 void, ,传入的 func 需要采用以下形式 Func<TValue, void> (这相当于 Action<TValue>).

许多其他答案暗示您不能像表达式一样链接语句,但我不确定这个想法来自哪里。我们可以想到 ; 作为二元中缀运算符出现在语句之后,采用两个类型的表达式 void 并将它们组合成一个类型的表达式 void.

声明 -> 按顺序遵循的说明
表达式 -> 返回值的求值

语句基本上就像算法中的步骤或指令,语句的执行结果是指令指针的实现(在汇编程序中称为)

乍一看,表达式并不暗示执行顺序,它们的目的是评估并返回一个值。在命令式编程语言中,表达式的求值是有顺序的,但这只是因为命令式模型的原因,而不是它们的本质。

声明示例:

for
goto
return
if

(所有这些都意味着执行行(语句)前进到另一行)

表达式示例:

2+2

(这并不意味着执行的想法,而是评估的想法)

陈述是语法上完整的句子。表达式则不然。例如

x = 5

读为“ x获取5”。这是一个完整的句子。代码

(x + 5)/9.0

读:“ x Plus 5全部除以9.0。”这不是一个完整的句子。该声明

while k < 10: 
    print k
    k += 1

是一个完整的句子。请注意,循环头不是;“while k < 10,”是一个从句。

陈述,

语句是构建所有 C# 程序的过程构建块。语句可以声明局部变量或常量、调用方法、创建对象或为变量、属性或字段赋值。

一系列用大括号括起来的语句形成一个代码块。方法体是代码块的一个示例。

bool IsPositive(int number)
{
    if (number > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

C# 中的语句通常包含表达式。C# 中的表达式是包含文字值、简单名称或运算符及其操作数的代码片段。

表达,

表达式是可以计算为单个值、对象、方法或命名空间的代码片段。两种最简单的表达式类型是文字和简单名称。文字是没有名称的常量值。

int i = 5;
string s = "Hello World";

i 和 s 都是标识局部变量的简单名称。当这些变量在表达式中使用时,将检索变量的值并将其用于表达式。

我更喜欢的意思是 statement 在这个词的形式逻辑意义上。它可以改变计算中一个或多个变量的状态,从而能够对它们的值做出正确或错误的陈述。

我想,当引入新的术语或词语、现有词语被“重新利用”或者用户不了解他们所描述的现有的、已建立的或“正确的”术语时,计算世界和一般科学总是会出现混乱。

我对这里的任何答案都不满意。我查看了语法 C++(ISO 2008). 。然而,也许出于教学和编程的目的,答案可能足以区分这两个元素(尽管现实看起来更复杂)。

语句由零个或多个表达式组成,但也可以是其他语言概念。这是语法的扩展巴科斯诺尔形式(语句摘录):

statement:
        labeled-statement
        expression-statement <-- can be zero or more expressions
        compound-statement
        selection-statement
        iteration-statement
        jump-statement
        declaration-statement
        try-block

我们可以看到 C++ 中被视为语句的其他概念。

  • 表达式语句s 是不言自明的(语句可以由零或 更多的 表达式,仔细阅读语法,很棘手)
  • case 例如是一个 标记语句
  • 选择声明if if/else, case
  • 迭代语句while, do...while, for (...)
  • 跳转语句break, continue, return (可以返回表达式), goto
  • 声明-声明 是一组声明
  • 尝试块 是语句代表 try/catch
  • 语法上可能还有更多

这是显示表达式部分的摘录:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • 表达式通常是或包含赋值
  • 条件表达式 (听起来有误导性)指的是运算符的使用(+, -, *, /, &, |, &&, ||, ...)
  • 抛出表达式 - 呃?这 throw 子句也是一个表达式

这是我发现的最简单答案之一的总结。

最初由 Anders Kaseorg 回答

语句是执行某些操作的完整代码行,而表达式是计算结果为值的代码的任何部分。

表达式可以使用运算符“水平”组合成更大的表达式,而语句只能通过逐个写入或使用块结构来“垂直”组合。

每个表达式都可以用作语句(其作用是计算表达式并忽略结果值),但大多数语句不能用作表达式。

http://www.quora.com/Python-programming-language-1/Whats-the-difference- Between-a-statement-and-an-expression-in-Python

为了改进和验证我之前的答案,编程语言术语的定义应在适用时从计算机科学类型理论进行解释。

表达式具有除 Bottom 类型之外的类型,即它有一个价值。语句具有 Unit 或 Bottom 类型。

由此可见,一条语句只有在产生副作用时才能在程序中产生任何影响,因为它要么不能返回值,要么只返回不可分配的 Unit 类型的值(在某些语言中,例如一个C void) 或(例如在 Scala 中)可以被存储以用于语句的延迟计算。

显然是一个 @pragma 或一个 /*comment*/ 没有类型,因此与语句不同。因此,唯一没有副作用的语句类型是非操作。不操作仅用作未来副作用的占位符。由于声明而产生的任何其他操作都将产生副作用。再次是编译器提示,例如 @pragma, 不是一个语句,因为它没有类型。

最准确地说,一个声明必须有一个 “副作用” (IE。 势在必行) 并且表达式必须 A 价值 类型(即不是底部类型)。

语句类型 是单位类型,但由于停止定理,单位是虚构的,所以可以说 底型.


Void 不完全是底部类型(它不是所有可能类型的子类型)。它存在于以下语言中 没有完整健全的类型系统. 。这听起来可能像是一个势利的说法,但完整性 例如方差注释 对于编写可扩展软件至关重要。

让我们看看维基百科对这个问题是怎么说的。

https://en.wikipedia.org/wiki/Statement_(computer_science)

在计算机编程中,语句是语句的最小独立元素 至关重要的 表达的编程语言 一些行动 要进行。

许多语言(例如C) 区分语句和定义,语句仅包含可执行代码,定义声明标识符,而表达式仅计算一个值。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top