用户定义的字符串字面量与其他用户定义的字面量

6

让我们考虑以下来自C++11标准(确切地说是N3376版)的引用:

(2.14.8.5)

If L is a user-defined-string-literal, let str be the literal without its ud-suffix and let len be the number of code units in str (i.e., its length excluding the terminating null character). The literal L is treated as a call of the form

     operator "" X (str , len )

然而,对于所有其他类型的用户定义字面量(浮点数、整数、字符),即使字面量本身以字符串形式传递,其长度也永远不会被传递。例如:

42_zzz; // calls operator "" _zzz("42") and not operator "" _zzz("42", 2)

为什么要区分字符串和非字符串用户自定义字面值?或者说,为什么实现在 UD 字符串字面值中传递 len? 就像其他字面值一样,长度可以通过空终止符来推断。我漏掉了什么吗?

可能与编码/字符集有关。在那段之前的所有段落都有“[注意:序列c1c2...ck只能包含基本源字符集中的字符。—结束注意]”。 - Mat
@Mat:但是采用其他编码或字符集的字符串仍然以空字符结尾,不是吗? - Armen Tsirunyan
空终止符不足以解决问题。我猜“基本源字符集”不包括\0 - Mat
2个回答

8

对于字符串文字而言,其中嵌入了空字符 "a\0b" 在字符串序列中是有可能的。为了使实现能够消耗整个字符串文字,即使存在嵌入的空字符,它需要知道该文字的长度。用户自定义文字的其他形式不能包含嵌入的零字符。


顺便提一下,即使在C99中也可以定义一个宏,当用标识符和字符串字面值调用时,它将创建一个以该名称命名的编译时常量结构体,其中包含字符串的长度,后跟一个数组,其中包含字符串的文本但不包括尾随的null字符(不确定在C11下是否可以干净编译)。不确定在C++中是否可能使用用户定义的字符串字面值类型来实现这样的操作,但如果可以的话,它似乎会非常方便。 - supercat
@supercat:我并不否认你可以确定字符串字面量的长度。但是,如果你只传递了一个 char const*,你就无法确定字符串字面量的长度!传统的方法是通过查找空字符来确定大小,但这只能确定字符串到第一个空字符的大小。需要某种方式来获取字符串字面量的大小(这也是你描述的宏所依赖的内容:它只使用 sizeof(literal)-1 来确定字面量中字符的数量(不包括结尾的 \0)。 - Dietmar Kühl
当然,需要字符串的大小,这就是为什么我提到的结构在字符串之前放置它的原因;我的观点是即使在C宏中,也可以将文字字符串的长度用作整数常量。顺便说一下,我的代码使用了不同的宏,根据字符串是0-63字节、0-2047字节还是0-16777215字节[使用1、2或4字节前缀]生成不同的结构。还有宏来初始化带有一、二和四字节前缀的边界检查字符串缓冲区。字符串处理方法自动检测前缀类型,并且还可以... - supercat
处理一个特殊的“间接标志”前缀字节,后跟描述字符串的结构。想要将整个字符串传递给方法的代码可以传递直接指针;想要传递部分的代码可以创建描述该部分的结构并传递指向该结构的指针。安全的边界检查字符串处理,无需手动跟踪字符串长度。 - supercat

6

在C/C++中,字符串始终以空字符结尾,但这并不意味着它们不能包含嵌入的\0字符,例如你可能有一个字符串"1234\05678",虽然该字符串已经以空字符结尾,但它仍然包含一个额外的'\0'字符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接