如何反向验证某个feature在特定标准才开启?case语句fallthrough?如何理解Swift “case let xxx:“?case语句可以动态筛选?

目录

如何反向验证某个feature在特定标准才开启?

case语句fallthrough

case默认不break有什么优势?

如何理解Swift "case let xxx:"?

如何理解Swift "case 10 ... 20 = a"这种条件表达式?

case语句可以动态筛选?

switch/case语句

条件类型

switch结构起源

Fall Through


如何反向验证某个feature在特定标准才开启?

以"C++17引入了switch用初始化表达式"为例,

switch (int x = value; x) {
case 1 ... 10:
}

g++ -std=c++14 demo.cpp

-> 警告如下:init-statement in selection statements only available with ‘-std=c++17’ or ‘-std=gnu++17

g++ -std=c++17 demo.cpp
-> 无任何警告。

case语句fallthrough

大家知道,C/ObjC/C++的switch/case语句中,每个case跟随的语句,如果没有break语句会默认fallthrough. 这产生了一个经常发生bug的地方,不小心遗漏break导致意外的fallthrough.

  • Swift改善了这一点,case语句后面默认隐式带有"break", 如需要fallthrough,需特别写fallthrough语句。它的设计和C语言完全相反,首先默认带break,避免不小心的bug,特别需要fallthrough就指定。
  • Go语言同样以安全优先,默认带break,如需fallthrough需特别写fallthrough.
  • Pascal语言每个case语句默认会结束上一个case语句。

case默认不break有什么优势?

  • 对于C语言而言,case标号其实就是普通的label,汇编语言理解为可以跳转的label. 当有些解析程序对于多个case用同样解析方法,这种设计很方便简洁。

如何理解Swift "case let xxx:"?

一样,我们可以找到Swift switch语法定义:Switch Statements | swift.org

case-label → attributes? case case-item-list :
case-item-list → pattern where-clause? | pattern where-clause? , case-item-list

其实,let xxx是一种idenfifier pattern (Identifier Patterns | swift.org), 如下:

pattern → wildcard-pattern type-annotation?
pattern → identifier-pattern type-annotation?
pattern → value-binding-pattern
pattern → tuple-pattern type-annotation?
pattern → enum-case-pattern
pattern → optional-pattern
pattern → type-casting-pattern
pattern → expression-pattern

如何理解Swift "case 10 ... 20 = a"这种条件表达式?

Swift提供了Case Pattern Initializer用来初始化一个变量,如下可以判断a是否在10~20之间。
if case 10 ... 20 = a {
print("a is in 10 ~ 20")
}

可参考Swift语言标准条件语句语法:
condition → expression | availability-condition | case-condition | optional-binding-condition
case-condition → case pattern initializer
Refer to: Statements | Documentation (swift.org)

case语句可以动态筛选?

传统意义上,C/ObjC/C++不支持case匹配的动态筛选,只有静态且具体值对应匹配。

  • Swift提供了case <pattern> 可以动态筛选条件,比较灵活强大。技术上并不复杂,只是将之前的单一静态条件判断变成<pattern>条件判断语句。
  • C++17允许switch初始化表达式(switch 语句 (C++) | Microsoft Learn),但case依然局限于具体值范围,不能加入变量条件。
    GNU扩展对C/C++都允许case范围匹配,例如如下case 1 ... 10,但MSVC不支持。
    switch (int x = value; x) { // Only C++17 works
    case 1 ... 10: // GNU C/C++ both works
    }
    - 此处需特别注意,case 1...10会编译出错,"..."前后必须有空格(Case Ranges | GCC).
    - 可能会发现用gcc -std=c89或g++ -std=c++98都可以编译过如上case 1 ... 10,不要惊慌,可能你使用的GCC版本default就启用case范围匹配,哪怕指定用标准C语言或者C++也不能阻挡GCC对范围匹配的支持。
  • C# 7.0 引入的模式匹配(Pattern Matching)允许开发者在 switch 语句中使用更复杂的条件来匹配不同的情况,不止基于常量值,还能基于数据类型、属性、条件关系等进行分支,因为太灵活了,此处不举例了。
  • Java 12对switch表达式进行优化,允许多值并带有条件判断。
  • JavaScript case允许任意表达式,且case表达式是运行时求值而非C/C++编译期求值,所以JS的case表达式性能会低很多。
  • Kotlin 用when语句支持传统语言的switch/case,也支持范围匹配和表达式作为条件判断。

switch/case语句

多路分支选择switch/case是if/else if/else的好看版本,switch中default语句对应if的else语句。每个case对应汇编代码的label, 编译器插入多条jmp语句实现不同分支跳转.

条件类型

  • C/C++条件类型必须是整型、字符或枚举,不能是字符串。
  • C#除了C/C++支持的类型,还可以支持字符串形式,Java 7 switch条件加入了字符串类型。
  • Python 3.10加入了match case语句支持多条件选择。
  • Ada用case/when结构。
  • Shell的case语句使用通配符测试模式,可以使用形如*.txt匹配所有以.txt结尾的文本,这比编译型语言更自由。Pattern还可用|组合做多重匹配。
  • PHP作为脚本语言,case参数可以是字符串。
  • Kotlin 用when代替以往的switch,例如:
     when (a) {
            1 -> println("a is 1")
            2 -> println("a is 2")
            else -> println("a is not 1, 2")
        }
        when (a)  {
            1, 2 -> println("a is 1 or 2")
            else -> println("a is not 1, 2")
        }
        when {
            a == 1 -> println("a is 1")
            a == 2 -> println("a is 2")
            else -> println("a is not 1, 2")
        }
  • Pascal 采用 case xxx of 开头,后面紧跟不同case以及else. 例如:
    case ch of
    'a' : Writeln("a");
    else: Writeln("not a");
    end;
    • case参数可以用逗号分隔多个参数,也可以用 .. 指代连续范围。
  • 仓颉 提供match/case条件匹配。

switch结构起源

  • 最早Algol 68引入了多重选择语句switch/case, 为后续大部分编程语言所用,比如C/C++/Java/C#.
  • Fortran最早没有,在Fortran 77版本引入了类似的select/case语句。
  • Cobol 85引入了evaluate语句,类似于switch/case.
  • Ada支持case一条语句多条件和范围设定,形如when 1 | 2 | 10 .. 15表示为1或2或10~15的范围。
  • 标准C语言不支持case语句范围,GNU C扩展了此功能,示例:case 10 ... 1000: 表示在10到100范围内。

Fall Through

case贯穿在某些时候特别有效,比如libc %i用%d同一套输出逻辑,仅仅将%i的case和%d地方一起即可。

  • C/C++有着近乎汇编的控制能力, 对fall through的支持最自由。
  • Java也支持贯穿,因不支持goto对于某些处理逻辑不那么灵活。
  • C#更有意思,支持贯穿,但必须用goto语句显式指明跳转哪里。


若文章对您有帮助,欢迎关注 程序员小迷 。助您在编程路上越走越好!

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是 程序员小迷 (致力于C、C++、C#、Android、iOS、Java、Kotlin、Objective-C、Swift、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值