当前位置: 首页 > ai >正文

Ctrl + D是如何与内核文件结束符对应的?如何模拟文件结束符?数字中间为什么不能插入空格或逗号?丰富多彩的语句结束符或分隔符?语句结束符?

目录

Ctrl + D是如何与内核文件结束符对应的?

如何模拟文件结束符?

哪些编程语言支持数值中插入分隔符更容易看清楚?

下划线分隔符

数字中间为什么不能插入空格或逗号?

丰富多彩的语句结束符或分隔符

误用分号

语句结束符

不同语言的结束符

更改语句结束符


Ctrl + D是如何与内核文件结束符对应的?

*nix系统的终端一般会输入Ctrl + D代表输入流结束,Linux和macOS均是如此,尽管Windows用Ctrl + Z,仅仅是外部按键表现,最终目的是一样的。如下以Linux 6.11为例讲解。

  • 每开启一个终端会开启一个terminal设备,以tty为例,对应于内核的tty_struct (include\linux\tty.h).
  • tty默认配置会定义常见控制按键映射关系:
    #define INIT_C_CC { \
    [VINTR] = 'C'-0x40, \
    [VQUIT] = '\\'-0x40, \
    [VERASE] = '\177', \
    [VKILL] = 'U'-0x40, \
    [VEOF] = 'D'-0x40, \
    [VSTART] = 'Q'-0x40, \
    [VSTOP] = 'S'-0x40, \
    [VSUSP] = 'Z'-0x40, \
    [VREPRINT] = 'R'-0x40, \
    [VDISCARD] = 'O'-0x40, \
    [VWERASE] = 'W'-0x40, \
    [VLNEXT] = 'V'-0x40, \
    INIT_C_CC_VDSUSP_EXTRA \
    [VMIN] = 1 }

    上面的VEOF代表文件结束符对应的按键数值是4.
  • 如上INIT_C_CC会被带入kernel tty标准属性设定 tty_io.c (drivers/tty)
    struct ktermios tty_std_termios = { /* for the benefit of tty drivers /
    .c_iflag = ICRNL | IXON,
    .c_oflag = OPOST | ONLCR,
    .c_cflag = B38400 | CS8 | CREAD | HUPCL,
    .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN,
    .c_cc = INIT_C_CC,
    .c_ispeed = 38400,
    .c_ospeed = 38400,
    / .c_line = N_TTY, */
    };
  • 用户层可通过tcgetattr函数获取对应终端tty (struct termios)的c_cc[VEOF]信息,一般而言默认为0x4, 对应于ASCII EOT (End Of Transmission).
    - 也可用stty -a命令获取当前tty的设定:
    speed 38400 baud; rows 17; columns 198; line = 0;
    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?;
  • 综上,Ctrl + D触发按键4,内核根据它注册的EOF传递给上层EOF讯息.

如何模拟文件结束符?

  • *nix系统默认可用Ctrl + D按键可给系统发送EOT信号,对应于stdin的EOF.
    - Windows对应Ctrl + Z.
  • *nix系统可用echo命令发送ASCII码4(EOT)来模拟文件结束。
    echo -e "\004"
    例如,一个程序a.out用getchar读取字符,如下可完成向a.out发送EOF.
    echo -e "\004" | ./a.out
    - 如上还会额外发送'\n'字符,echo -ne "\004"只会发送EOT.

哪些编程语言支持数值中插入分隔符更容易看清楚?

除了C/ObjC不支持,C++/Java/C#/JS/Swift/VB.NET/Rust/Go/Python 3.6/仓颉 等语言均支持,分隔符一般选择是下划线_, 也有选择用单引号。

  • C++:C++14标准引入了对数字字面量中使用单引号'做分隔支持。
    当然,用-std=c++11会出现build错误。
  • C#:从C# 7.0开始,可以使用下划线在数字字面量中增加可读性。
    可通过编译选项/langversion:6.0确认此功能在7.0以上才会支持:error CS8059: 功能“数字分隔符”在 C# 6 中不可用,请使用 7.0 或更高的语言版本。
    C# 7.2开始支持十六进制数值和二进制数值(0x开头和0b开头)在0x和0b后面插入下划线。
  • Java:从Java 7开始,Java支持在数字字面量中使用下划线。
    反向验证,可通过 -target 1.6 -source 1.6选项确认数字字面量存在下划线有编译错误。
  • JavaScript 从 ES2021 版本开始支持在数值字面量中使用下划线作为分隔符。
  • VB.NET之前不支持,VB.NET最新版已经支持数值中用下划线分隔。例如:
    Dim a as Integer = 1_000
  • Rust/Swift/Go语言都支持数值中用下划线分隔。
  • Python 3.6开始也支持数值用下划线分隔,具体参考:PEP 515 – Underscores in Numeric Literals.
  • 仓颉 支持用下划线在数值字面量中,不论是整型还是浮点型。
    例如1_23代表123,1.2_3代表1.23.

下划线分隔符

你可能会困惑,C#也允许数值中有多个连续的下划线,其实本质上,编译器在解析数值字面量直接忽略下划线,所以多个连续下划线不影响解析,例如 1__200.

  • 需要注意,下划线不能在字面量开头或者结尾。

数字中间为什么不能插入空格或逗号?

整数10000不能写成10 000或者10,000, 原因在于为了简化编译器parser字面量的复杂度。一个标准的编译器词法分析器遇到数值类型会不断获取数字并累积,一旦遇到非数字就会退出。如果允许数字中间加空格或者逗号,词法分析器将更复杂,也容易破坏已有语言的结构,产生冲突。当然,一些高级语言为了提升长数值可读性,可以允许数字中间加入一些分隔符:

  • Python (>=3.6版本)可以在数字中间加下划线
    number = 1_000_000
  • Swift可以在整数、浮点数中间加下划线增强可读性
    let number = 1_000_000.000_001

丰富多彩的语句结束符或分隔符

  • C/C++/ObjC/Java/C#/Pascal/PHP 等语言用分号分隔。
  • Basic/Python用换行分隔。
  • SQL语言既可以用换行也可以用分号,在不同语句在同一行时用分号,也支持更改语句分隔符。
  • Swift/JavaScript/Go/仓颉/Kotlin 结束符既可用换行,也可用分号。
    同一行写多个语句,用分号分隔。
  • VB采用换行或者冒号:作为结束符,下划线_作为续行符,VBScript和VB一样。
    • VB 2010之后,行续行符逐渐变得可选,即编译器更加智能,并不是直接以换行作为语句的结束,可以更懂程序员的代码。
    • 同一行有多个语句,用冒号作为语句分隔符。用下划线续行代表上下行属于同一个语句。
  • Rust语句结束符是分号,如果是块语句最后一个语句可以忽略分号。

误用分号

  • C语言分号作为语句的结束,如果误用在if、for和while条件语句之后,可能造成提前结束。
    例如
    if (x == 1);
    printf("is 1");
    这里if判断这行就已经结束了。幸运的是,GCC提供-Wmisleading-indentation选项检测这样的问题。

    if (a < 0)
    return
    printf("fail");
    这里return语句和后面的printf是连在一起作为一个语句。可惜的是,GCC/MSVC打开-Wall也不能提示可能的隐患。
  • C/C++ 结构体定义的最后需要有分号,习惯写C#/Java类定义可能忘记这个设定,造成奇怪的编译结果。比如,忘记了分号,结构体定义被当成了一个类型作为返回值。

语句结束符

这个话题听起来很简单,但不同编程语言的不同语法产生了五花八门的语句结束符。大部分编程语言以换行或者分号作为结束符,当然要排除有续行符的情况。

不同语言的结束符

  • C/C++/Java/C#用分号分隔。
  • Basic/Python用换行分隔。
  • SQL语言既可以用换行也可以用分号,在不同语句在同一行时用分号,也支持更改语句分隔符。
  • Swift/JavaScript/Go语句既可用换行,也可用分号。
  • VB采用换行或者冒号:作为结束符,下划线_作为续行符。VBScript和VB一样。

更改语句结束符

  • MySQL提供DELIMITER修改分隔符的方式,但其他SQL语言未必遵循。


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

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

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

http://www.xdnf.cn/news/5235.html

相关文章:

  • (剪映)视频添加字幕
  • SEO长尾关键词优化实战技法
  • 利用大型语言模型有效识别网络威胁情报报告中的攻击技术
  • webpack和vite区别
  • Go语言超时控制方案全解析:基于goroutine的优雅实现
  • 移动零--双指针
  • Docker 使用总结及完整示例介绍
  • 【天府诸葛杯】九天画芯 FSHD 三色光源技术晋级复赛:突围下一代底层显示技术
  • 数仓-如何保障指标的一致性
  • MySQL 索引和事务
  • 电子电路:光子是不是粒子?
  • 基于OpenCV的人脸识别:FisherFaceRecognizer算法
  • SolidWork-2023 鼠標工程
  • Java集合
  • Qt中的RCC
  • 如何避免在CMD中分段发送问题导致大模型多段回复的问题?
  • Day115 | 灵神 | 二叉树 | 二叉搜索树中的众数
  • Redis 哨兵
  • DIP依赖倒置原则
  • 第十课认识约数
  • 蓝牙身份证阅读器使用Uniapp调用二次开发demo
  • 逆向学习笔记(代码)
  • Linux `uptime` 指令详解与系统监控指南
  • 计算机体系结构一些笔记
  • C++中的继承与多态
  • 【Redis进阶】持久化
  • SpringMVC面试内容
  • 【无标题】I/O复用(epoll)三者区别▲
  • JS DOM操作与事件处理从入门到实践
  • 无线网络设备中AP和AC是什么?有什么区别?