为什么不选择空格字符作为 C + + 14位数字分隔符?

从 C + + 14开始,多亏了 N3781(它本身并没有回答这个问题) ,我们可以编写如下代码:

const int x = 1'234; // one thousand two hundred and thirty four

目的是改进这样的代码:

const int y = 100000000;

让它更具可读性。

在 c + + 11中,下划线(_)已经被用户定义的文字取代了,而且逗号(,)存在本地化问题 & mash,许多欧洲国家令人困惑地使用 & 匕首;作为小数点 & mash,并且与逗号操作符发生冲突,尽管我确实想知道现实世界中的代码可能会因为允许使用例如 1,234,567而被破坏。

不管怎样,一个更好的解决方案似乎是太空人:

const int z = 1 000 000;

这些相邻的数字文字标记可以像字符串文字一样由预处理器连接起来:

const char x[5] = "a" "bc" "d";

相反,我们得到了撇号(') ,我所知道的任何书写系统都没有使用它作为数字分隔符。

选择撇号而不是简单的空格有什么原因吗?


令人困惑的是,所有这些语言,在文本中,都保持着逗号“分解”原子句的概念,句号起到“终止”句子的作用,至少对我来说,这非常类似于一个逗号“分解”数字的整数部分,句号“终止”它准备进行小数输入。

18254 次浏览

之前的一篇论文 N3499告诉我们,尽管比亚内自己建议空间作为分隔符:

虽然这种方法与一种常见的字体风格是一致的,但它存在一些兼容性问题。

  • 它与 编号的语法不匹配,至少需要扩展该语法。
  • 更重要的是,当范围[ a-f ]中的十六进制数字跟在空格后面时,会出现一些语法歧义。预处理器将不知道是否从空格之后开始执行符号替换。
  • 这可能会降低抓取“文字”的编辑工具的可靠性。

我想下面这个例子就是我们注意到的主要问题:

const int x = 0x123 a;

尽管在我看来,这个理论基础相当薄弱,我仍然想不出一个现实世界的例子来打破它。

“编辑工具”的原理甚至更糟,因为 1'234基本上打破了人类已知的所有语法高亮显示器(例如 Markdown 在上述问题中使用的高亮显示器!)使得更新版本的高亮显示器更加难以实现。

尽管如此,不管是好是坏,这就是导致使用撇号的原因。

我假设这是因为,在编写代码时,如果您到达“行”(屏幕的宽度)的末尾,就会发生自动换行(或“换字”)。这会导致 int 被分成两半,一半在第一行,另一半在第二行... 这样,在 word-wrap的情况下,它们都会保持在一起。

维基百科,我们有一个很好的例子:

auto floating_point_literal = 0.000'015'3;

这里,我们有 .操作符,然后如果遇到另一个操作符,我的眼睛会等待一些可见的东西,比如逗号或其他东西,而不是空格。

所以撇号在这里比空格要好得多。

如果使用空格,它将是

auto floating_point_literal = 0.000 015 3;

感觉不像撇号那么正确。


本着 Albert Renshaw 的回答的同样精神,我认为撇号比轨道上的亮度竞赛提出的空间更加清晰。

type a = 1'000'000'000'000'000'544'445'555;
type a = 1 000 000 000 000 000 544 445 555;

空格用于许多事情,比如 OP 提到的字符串连接,不像撇号,在这种情况下,使用分隔数字的人可以清楚地看到。

当代码行变得很多时,我认为这将提高可读性,但我怀疑这是他们选择它的原因。


关于空间,值得一看的是这个 C 有个问题,它说:

这种语言不允许使用 int i = 10 000;(一个整数字面值是一个标记,中间的空格将它分成两个标记) ,但是将初始化器表示为一个计算字面值的表达式通常几乎不会产生任何费用:

int i = 10 * 1000; /* ten thousand */

的确,我看不出这样做有什么实际意义:

if (a == 1 1 1 1 1) ...

所以数字可以合并而不会产生歧义 那十六进制数呢?

0 x 1 a B 2 3

这样做无法消除与输入错误之间的歧义(通常我们会看到一个错误)

不使用空白的明显原因是新行也是 空白,C + + 对待所有空白的方式是一样的 手,我不知道任何语言接受任意的空白 作为分离器。

据推测,可以使用 Unicode 0xA0(不换行空格) 最广泛使用的解决方案时,排版。我看到两个问题 但是: 首先,它不在基本字符集中,其次, 它没有视觉上的独特性,你看不出它不是一个空间 用普通编辑器查看文本。

除此之外,没有太多的选择。你不能使用逗号,因为 这已经是一个合法的令牌(类似 1,234的东西目前是 在一个上下文中,它可能会出现 在法律代码,例如 a[1,234]。虽然我不能完全想象任何真正的 代码实际上使用这个,有一个基本的规则,没有合法的程序, 无论多么荒谬,都应该悄悄地改变语义。

类似的考虑意味着也不能使用 _; 如果有一个 #define _234 * 2,那么 a[1_234]就会默默地改变 密码。

我不能说我对 '的选择特别满意,但是 在欧洲大陆确实有使用的优势,至少在 (我似乎记得曾经在德语中看到过,因为 例如,虽然在典型的运行文本,德国,像大多数其他 语言,将使用一个点或一个不破坏的空间。但也许它是 '的问题是解析; 序列 '1'是 已经合法了,就像 '123'一样。所以像 1'234这样的东西可能是 1, 然后是一个字符常量的开始; 我不知道你 我们必须向前看才能作出决定。法律上没有先后次序 一个整数常数后跟一个字符的 C + + 语言 不变,所以违反法律没有问题,但这意味着 词汇扫描突然变得非常依赖上下文。

(关于你的评论: 选择一个 十进制分隔符或千分隔符。例如,小数点 当然不是句号,它们只是武断的惯例。)

它与语言的解析方式有关。编译器作者很难重写他们的产品来接受空格分隔的文字。

另外,我不认为用空格分隔数字是很常见的。在我看来,它总是非空格字符,即使在不同的国家也是如此。

float floating_point_literal = 0.0000153;   /* C, C++*/


auto floating_point_literal = 0.0000153;    // C++11


auto floating_point_literal = 0.000'015'3;  // C++14

评论并不会带来伤害:

/*  0. 0000 1530 */
float floating_point_literal = 0.00001530;

二进制字符串很难解析:

long bytecode = 0b1111011010011001; /* gcc , clang */


long bytecode = 0b1111'0110'1001'1001;  //C++14
// 0b 1111 0110 1001 1001  would be better, really.
// It is how humans think.

一个需要考虑的宏:

#define B(W,X,Y,Z)    (0b##W##X##Y##Z)
#define HEX(W,X,Y,Z)  (0x##W##X##Y##Z)
#define OCT(O)        (0##O)






long z = B(1001, 1001, 1020, 1032 );


// result :  long z = (0b1001100110201032);


long h = OCT( 35);


// result :  long h  = (035); // 35_oct => 29_dec


long h = HEX( FF, A6, 3B, D0 );


// result :  long h  = (0xFFA6BD0);