【发布时间】:2013-07-29 14:39:30
【问题描述】:
语法和语义在编程语言(如C、C++)中有什么区别?
【问题讨论】:
-
我想投票,但没有明显的研究成果。
标签: syntax programming-languages semantics
语法和语义在编程语言(如C、C++)中有什么区别?
【问题讨论】:
标签: syntax programming-languages semantics
TL;博士
总而言之,句法是只关心句子本身是否对语言的语法有效的概念。语义是关于句子是否具有有效含义。
长答案:
语法是关于结构或语言的语法。它回答了这个问题:我如何构造一个有效的句子?所有语言,甚至是英语和其他人类(又称“自然”)语言都有语法,即定义句子是否正确构造的规则。
以下是一些C语言语法规则:
语义是关于句子的意义。它回答了以下问题:这句话有效吗?如果是这样,这句话是什么意思?例如:
x++; // increment
foo(xyz, --b, &qrs); // call foo
是语法上有效的 C 语句。但它们是什么意思?尝试将这些语句转换为可执行的指令序列是否有效?这些问题是语义的核心。
考虑第一条语句中的 ++ 运算符。首先,尝试这样做是否有效?
最后,请注意,某些语义无法在编译时确定,因此必须在运行时进行评估。在 ++ 运算符示例中,如果 x 已经是其数据类型的最大值,那么当您尝试将 1 添加到它时会发生什么?另一个例子:如果你的程序试图取消引用一个值为 NULL 的指针会发生什么?
【讨论】:
x 处于其数据的最大值并且将1 添加到其中,则会导致一些奇怪的输出(0),这不是语义错误吗?
UINT_MAX + 1 == 0)。有符号溢出未定义。现代编译器通常有INT_MAX + 1 == INT_MIN,但有些情况你不能指望它(例如for (i = 0; i <= N; ++i) { ... },其中N是INT_MAX不是无限的,具体取决于优化;参见blog.llvm.org/2011/05/what-every-c-programmer-should-know.html )。
语法是指一种语言的结构,将其etymology 追溯到事物的组合方式。
例如,您可能需要通过声明类型、名称和分号来将代码放在一起,以确保语法正确。
Type token;
另一方面,语义是关于意义的。 编译器或解释器可能会抱怨语法错误。你的同事会抱怨语义。
【讨论】:
维基百科有答案。阅读 syntax (programming languages) 和 semantics (computer science) 维基页面。
或者想想compiler 或interpreter 的工作。第一步是lexical analysis,其中通过将字符串划分为词位然后parsing 生成标记,从而构建一些abstract syntax tree(这是语法的表示)。接下来的步骤涉及转换或评估这些 AST(语义)。
另外,请注意,如果您定义了一个 C 的变体,其中每个关键字都转换为其法语等效项(因此 if 变为 si,do 变为 faire,else 变为 sinon 等等...) 你肯定会改变你的语言的语法,但你不会改变太多的语义:用法语-C 编程不会更容易!
【讨论】:
语义是您的代码的含义——您可以在伪代码中描述的含义。语法是真正的结构——从变量名到分号。
【讨论】:
【讨论】:
语法是表达式、语句和程序单元的结构或形式,但语义是这些表达式、语句和程序单元的含义。 语义直接来自语法。 语法是指特定编程语言指定的代码结构/形式,但语义处理分配给符号、字符和单词的含义。
【讨论】:
派对迟到了 - 但对我来说,这里的答案似乎正确但不完整。
务实地,我会区分三个层次:
1.语法
语法是语言的形式语法,它指定了编译器将识别的格式良好的语句。
所以在C语言中,变量初始化的语法是:
data_type variable_name = value_expression;
例子:
int volume = 66 * 22 * 55;
在提供类型推断的 Go 中,一种初始化形式是:
variable_name := value_expression
例子:
volume := 66 * 22 * 55
显然,Go 编译器无法识别 C 语法,反之亦然。
2。低级语义
语法与形式有关,语义与意义有关。
在自然语言中,一个句子可以在句法上正确但在语义上毫无意义。例如:
The man bought the infinity from the store.
这句话在语法上是正确的,但在现实世界中没有意义。
在底层,编程语义关注的是语法正确的语句是否也符合开发人员使用语言类型系统表达的语义规则。
例如,这是一个语法正确的 Java 赋值语句,但在语义上它是一个错误,因为它试图将 int 分配给 String
String firstName = 23;
因此,类型系统旨在保护开发人员免于在低级别出现意外的含义失误。
像 JavaScript 或 Python 这样的松散类型语言提供的语义保护很少,而像 Haskell 或 F# 这样的具有表达类型系统的语言为熟练的开发人员提供了更高级别的保护。
例如,在 F# 中,您的 ShoppingCart 类型可以指定购物车必须处于以下三种状态之一:
type ShoppingCart =
| EmptyCart // no data
| ActiveCart of ActiveCartData
| PaidCart of PaidCartData
现在编译器可以检查您的代码没有试图将购物车置于非法状态。
在 Python 中,您必须编写自己的代码来检查有效状态。
3.高级语义
最后,在更高的层次上,语义关注的是代码要实现的目标——编写程序的原因。
这可以表示为可以用任何完整语言实现的伪代码。例如:
// Check for an open trade for EURUSD
// For any open trade, close if the profit target is reached
// If there is no open trade for EURUSD, check for an entry signal
// For an entry signal, use risk settings to calculate trade size
// Submit the order.
在这个(极其简化的)场景中,如果您的系统同时输入两笔 EURUSD 交易、输入方向错误的交易、错误计算交易规模等,您将犯下高级语义错误。
TL;博士
如果你搞砸了你的语法或低级语义,你的编译器会抱怨。
如果你搞砸了你的高级语义,你的程序就不适合目的,你的客户会抱怨。
【讨论】:
通常,代码的语法和语义分析在编译器的“前端”部分完成。
语法:编译器为每个关键字和符号生成标记:标记包含关键字的信息类型及其在代码中的位置。 使用这些标记,可以创建和分析 AST(抽象语法树的缩写)。 编译器在这里实际检查的是代码是否具有词法意义,即“关键字序列”是否符合语言规则?正如先前答案中所建议的,您可以将其视为语言的语法(而不是代码的意义/含义)。 旁注:此阶段报告语法错误。(将具有错误类型的令牌返回给系统)
语义:现在,编译器将检查您的代码操作是否“有意义”。 例如如果语言支持类型推断,如果您尝试将字符串分配给浮点数,则会报告语义错误。或两次声明相同的变量。 这些是“语法上”/语法上正确的错误,但在操作期间没有任何意义。 旁注:为了检查同一个变量是否被声明了两次,编译器管理一个symbol table
因此,这两个前端阶段的输出是带注释的 AST(带有数据类型)和符号表。
考虑到我们使用的正常语言;在这里,英语:
例如他去学校。 - 不正确的语法/句法,尽管他想传达正确的意义/语义。
例如他去寒冷。 - 寒冷是一个形容词。在英语中,我们可能会说这不符合语法,但它实际上是我能想到的最接近错误语义和正确语法的例子。
【讨论】:
他喝米饭(错误的语义-无意义,正确的句法-语法)
嗨喝水(正确的语义-有意义,错误的语法-语法)
【讨论】:
语法 编程语言是其表达式、语句和程序的形式 单位。它的语义是那些表达式、语句和程序单元的含义。例如,Java while 语句的语法是
while (boolean_expr) statement
这种语句形式的语义是当布尔值的当前值 表达式为真,执行嵌入语句。然后隐式控制 返回布尔表达式以重复该过程。如果布尔表达式 为 false,控制转移到 while 构造之后的语句。
【讨论】:
语法:它指的是语言的语法结构。如果您正在编写c语言。您必须非常小心地使用数据类型、标记 [它可以是文字或符号,如“printf()”。它有 3 个令牌,“printf, (, )”]。同样的,你必须非常小心,你如何使用函数,函数语法,函数声明,定义,初始化和调用它。
而语义,它涉及句子或语句的逻辑或概念。如果你说或写的东西超出概念或逻辑,那么你在语义上是错误的。
【讨论】: