通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

C++的字面值常量是什么

C++中的字面值常量是指在程序中直接使用的特定值。这些常量可以是整型、浮点型、字符、字符串和布尔值。它们在编程中起到代表特定值的作用,例如,数字7就是一个整型字面值常量,字符’A’是一个字符字面值常量,”Hello World”是一个字符串字面值常量。这些字面值常量在程序运行期间的值是不能被改变的。

一、C++的字面值常量

C++的字面值常量是在源代码中表示固定值的符号。以下是一些常见类型的字面值常量:

  1. 整型字面值常量:这是一种最常见的字面值类型。例如,数字5、100和-273都是整型字面值常量。我们还可以使用十六进制(如0x1F)、八进制(如017)或二进制(如0b1010)表示整数。
  2. 浮点型字面值常量:浮点型字面值常量用于表示小数,例如,3.14、-0.001或者1.6e-19。
  3. 字符字面值常量:字符字面值常量是单引号中的单个字符,例如,’a’、’Z’或’9’。还包括一些转义序列,如’\n’(换行符)、’\t’(制表符)和’\0’(空字符)。
  4. 字符串字面值常量:字符串字面值常量由双引号括起来的字符序列构成,例如,”hello, world”或者”12345″。
  5. 布尔字面值常量:布尔字面值常量只有两个:true和false。
  6. 空指针字面值常量:空指针字面值常量是nullptr。

这些字面值常量在程序运行期间的值是不能被改变的。在C++中,我们可以使用const关键字来创建常量变量,其值在初始化后也不能被改变。例如,const int days = 7; 这行代码创建了一个整型常量days,并初始化为字面值常量7。

在C++11中,还引入了一种新的字面值常量类型:用户定义字面值常量。这允许开发者自定义字面值常量的类型和值,使得代码更具可读性和表现力。例如,可以定义一个表示时间的字面值常量,如12h + 30min,这在某些特定领域的编程中非常有用。

二、C++ 变量和基本类型、字面值常量

像 42 这样的值,在程序中被当作字面值常量。称之为字面值是因为只能用它的值称呼它,称之为常量是因为它的值不能修改。每个字面值都有相应的类型,例如:0 是 int 型,3.14159 是 double 型。只有内置类型存在字面值,没有类类型的字面值。因此,也没有任何标准库类型的字面值。

整型字面值规则

定义字面值整数常量可以使用以下三种进制中的任一种:十进制、八进制和十六进制。当然这些进制不会改变其二进制位的表示形式。例如,我们能将值 20 定义成下列三种形式中的任意一种:

20     // decimal
024    // octal
0x14   // hexadecimal

以 0(零)开头的字面值整数常量表示八进制,以 0x 或 0X 开头的表示十六进制。

字面值整数常量的类型默认为 int 或 long 类型。其精度类型决定于字面值——其值适合 int 就是 int 类型,比 int 大的值就是 long 类型。通过增加后缀,能够强制将字面值整数常量转换为 long、unsigned 或 unsigned long 类型。通过在数值后面加 L 或者 l(字母“l”大写或小写)指定常量为 long 类型。

定义长整型时,应该使用大写字母 L。小写字母 l 很容易和数值 1 混淆。

类似地,可通过在数值后面加 U 或 u 定义 unsigned 类型。同时加 L 和 U 就能够得到 unsigned long 类型的字面值常量。但其后缀不能有空格:

128u     /* unsigned   */          1024UL    /* unsigned long   */
1L       /* long    */             8Lu        /* unsigned long   */

没有 short 类型的字面值常量。

浮点字面值规则

通常可以用十进制或者科学计数法来表示浮点字面值常量。使用科学计数法时,指数用 E 或者 e 表示。默认的浮点字面值常量为 double 类型。在数值的后面加上 F 或 f 表示单精度。同样加上 L 或者 l 表示扩展精度(再次提醒,不提倡使用小写字母l)。下面每一组字面值表示相同的值:

3.14159F            .001f          12.345L            0.
3.14159E0f          1E-3F          1.2345E1L          0e0

布尔字面值和字符字面值

单词 true 和 false 是布尔型的字面值:

bool test = false;

可打印的字符型字面值通常用一对单引号来定义:

‘a’         ‘2’         ‘,’         ‘ ‘ // blank

这些字面值都是 char 类型的。在字符字面值前加 L 就能够得到 wchar_t 类型的宽字符字面值。如:

L’a’

非打印字符的转义序列

有些字符是不可打印的。不可打印字符实际上是不可显示的字符,比如退格或者控制符。还有一些在语言中有特殊意义的字符,例如单引号、双引号和反斜线符号。不可打印字符和特殊字符都用转义字符书写。转义字符都以反斜线符号开始,C++ 语言中定义了如下转义字符:

newline 换行符  \n  horizontal tab 水平制表符   \t
vertical tab 纵向制表符  \v backspace 退格符  \b
carriage return 回车符  \r formfeed 进纸符  \f
alert (bell) 报警(响铃)符   \a backslash 反斜线  \\
question mark 疑问号  \? single quote 单引号  \’
double quote 双引号  \”

我们可以将任何字符表示为以下形式的通用转义字符:

\ooo

这里 ooo 表示三个八进制数字,这三个数字表示字符的数字值。下面的例子是用 ASCII 码字符集表示字面值常量:

\7 (bell)      \12 (newline)     \40 (blank)
\0 (null)      \062 (‘2’)        \115 (‘M’)

字符’\0’通常表示“空字符(null character)”,我们将会看到它有着非常特殊的意义。

同样也可以用十六进制转义字符来定义字符:

\xddd

它由一个反斜线符、一个 x 和一个或者多个十六进制数字组成。

字符串字面值

之前见过的所有字面值都有基本内置类型。还有一种字面值(字符串字面值)更加复杂。字符串字面值是一串常量字符,这种类型将在第 4.3 节详细说明。

字符串字面值常量用双引号括起来的零个或者多个字符表示。不可打印字符表示成相应的转义字符。

“Hello World!”                 // simple string literal
“”                             // empty string literal
“\nCC\较好tions\tfile.[cC]\n”   // string literal using newlines and tabs

为了兼容 C 语言,C++ 中所有的字符串字面值都由编译器自动在末尾添加一个空字符。字符字面值

‘A’ // single quote: character literal

表示单个字符 A,然而

“A” // double quote: character string literal

表示包含字母 A 和空字符两个字符的字符串。

正如存在宽字符字面值,如

  L’a’

也存在宽字符串字面值,一样在前面加“L”,如

L”a wide string literal”

宽字符串字面值是一串常量宽字符,同样以一个宽空字符结束。

字符串字面值的连接

两个相邻的仅由空格、制表符或换行符分开的字符串字面值(或宽字符串字面值),可连接成一个新字符串字面值。这使得多行书写长字符串字面值变得简单:

// concatenated long string literal
std::cout << “a multi-line “
“string literal “
“using concatenation”
<< std::endl;

执行这条语句将会输出:

a multi-line string literal using concatenation

如果连接字符串字面值和宽字符串字面值,将会出现什么结果呢?例如:

// Concatenating plain and wide character strings is undefined
std::cout << “multi-line ” L”literal ” << std::endl;

其结果是未定义的,也就是说,连接不同类型的行为标准没有定义。这个程序可能会执行,也可能会崩溃或者产生没有用的值,而且在不同的编译器下程序的动作可能不同。

多行字面值

处理长字符串有一个更基本的(但不常使用)方法,这个方法依赖于很少使用的程序格式化特性:在一行的末尾加一反斜线符号可将此行和下一行当作同一行处理。

正如第 1.4.1 节提到的,C++ 的格式非常自由。特别是有一些地方不能插入空格,其中之一是在单词中间。特别是不能在单词中间断开一行。但可以通过使用反斜线符号巧妙实现:

// ok: A \ before a newline ignores the line break
std::cou\
t << “Hi” << st\
d::endl;

等价于

std::cout << “Hi” << std::endl;

可以使用这个特性来编写长字符串字面值:

// multiline string literal
std::cout << “a multi-line \
             string literal \
             using a backslash”
             << std::endl;
return 0;
}

注意反斜线符号必须是该行的尾字符——不允许有注释或空格符。同样,后继行行首的任何空格和制表符都是字符串字面值的一部分。正因如此,长字符串字面值的后继行才不会有正常的缩进。

建议:不要依赖未定义行为

使用了未定义行为的程序都是错误的,即使程序能够运行,也只是巧合。未定义行为源于编译器不能检测到的程序错误或太麻烦以至无法检测的错误。

不幸的是,含有未定义行为的程序在有些环境或编译器中可以正确执行,但并不能保证同一程序在不同编译器中甚至在当前编译器的后继版本中会继续正确运行,也不能保证程序在一组输入上可以正确运行且在另一组输入上也能够正确运行。

程序不应该依赖未定义行为。同样地,通常程序不应该依赖机器相关的行为,比如假定 int 的位数是个固定且已知的值。我们称这样的程序是不可移植的。当程序移植到另一台机器上时,要寻找并更改任何依赖机器相关操作的代码。在本来可以运行的程序中寻找这类问题是一项非常不愉快的任务。

相关文章