globals及函数外部编写的代码是否属于语句?
这个问题不存在跨所有编程语言的统一答案,判断标准完全取决于你所用语言的官方语法规范对「语句(statement)」的边界定义,不同语言的设计差异极大,不能用单门语言的规则套所有场景。
C/C++/Java 等传统静态编译语言
写在函数外部的全局变量定义、函数声明/实现、struct/enum/union等自定义类型声明,完全不属于语句范畴。这类语法单元在语法树中属于和语句平级的*顶层声明(top-level declaration)*节点。
这类语言的语法规则对语句的出现位置有严格限制:普通执行类语句(比如赋值、函数调用、流程控制)只能写在函数/代码块内部,顶层作用域根本不允许出现这类语句——你在C语言函数外直接写一句printf("hello");会直接触发编译错误,就是最直接的验证。
举几个顶层非语句的例子:全局作用域下的int g_count = 0;是全局变量定义、struct User { char* name; int age; };是结构体类型声明、int add(int a, int b) { return a+b; }是函数定义,三者都不属于语句分类。Python/JavaScript 等动态脚本语言
顶层作用域允许出现语句,但不是所有顶层代码都归为语句:- 全局变量赋值、顶层表达式、顶层流程控制(比如直接写在脚本最外层的
if/for/while)属于普通执行类语句,会在脚本加载运行时按顺序逐行执行; - 函数定义(Python的
def、JS的function声明)、类定义(Python的class、JS的class声明)、导入声明(Python的import、JS的import)这类属于声明类语句,是这些语言语法中明确划定的语句子类——本质是这类语言的语法设计把声明归到了语句的分类下,不是所有语言都这么设计。
比如Python的官方语法规则中,顶层作用域的合法组成单元就是各类语句的集合,既包含执行类语句,也包含定义实体的声明类语句。
- 全局变量赋值、顶层表达式、顶层流程控制(比如直接写在脚本最外层的
Rust 等较新的静态语言
顶层作用域的合法语法单元叫做项(Item),包括函数定义、结构体/枚举定义、静态变量、常量、模块声明、use导入等,这些项都不属于语句。Rust中语句的合法出现位置仅限被{}包裹的代码块内部,比如块内的let绑定、表达式语句才属于语句分类;哪怕你在代码块内部写结构体、函数定义,这类也属于块级项,不算语句。
- 不要默认「能写在顶层的代码就是语句」:语法分类是严格按照语言的语法产生式划分的,和代码写的位置没有必然关系,很多语言的顶层作用域根本不接收普通语句,只允许声明/定义类语法单元。
- 不要把「声明」和「语句」的边界当成通用真理:部分语言把声明归为语句的子类,部分语言把二者作为完全独立的语法分类,这只是语法设计的选择差异,没有绝对的对错。
- 全局变量定义不能一概而论:C/C++中全局变量的初始化是在程序加载阶段完成的,不属于运行时执行的语句;但Python中全局变量的赋值是脚本运行到对应代码行时才执行的语句,二者的底层执行逻辑完全不同。
内容的提问来源于stack exchange,提问作者Random

