第 3 章 处理数据

面向对象编程(OOP)的本质是设计并扩展自己的数据类型。设计自己的数据类型就是让类型与数据匹配。内置的 C++类型分两组:基本类型和复合类型。

3.1 简单变量

为把信息存储在计算机中,程序必须记录 3 个基本属性:

  • 信息将存储在哪里
  • 要存储什么值
  • 存储何种类型的信息

3.1.1 变量名

C++提倡使用有一定含义的变量名。必须遵循几种简单的 C++命名规则。

  • 变量名只能使用字母字符数字下划线(_)
  • 名称的第一个字符不能是数字
  • 区分大小写
  • 不能将关键字用作名称
  • 两个下划线下划线大写字母开头的名称被保留给实现(编译器及其使用的资源)使用。以一个下划线开头的名称被保留给实现,用作全局标识符
  • 对名称长度没有限制,名称中所有字符都有意义。

3.1.2 整型

整数就是没有小数部分的数字,如 2、98、-5286 和 0。

不同 C++整型使用不同的内存量来存储整数。使用的内存量越大,可以表示的整数值范围也越大。另外,有的类型(符号类型)可表示正值和负值,而有的类型(无符号类型)不能表示负值。

C++的基本整型(按宽度递增的顺序排列)分别是 char、short、int、long 和 C++11 新增的 long long,其中每种类型都有符号版本和无符号版本,因此总共有 10 种类型可供选择。

char 类型有一些特殊属性(它最常用来表示字符,而不是数字)

3.1.3 整型 short、int、long 和 long long

计算机内存由一些叫做位(bit)的单元组成。C++的 short、int、long 和 long long 类型通过使用不同数目的位来存储值,最多能够表示 4 种不同的整数宽度。

字节(byte)通常指的是 8 位的内存单元。1KB 等于 1024 字节,1MB 等于 1024KB。

单位换算:

1 KB = 1024 byte

1 MB = 1024 KB

C++提供了一种灵活的标准,它确保了最小长度

  • short 至少 16 位
  • int 至少和 short 一样长
  • long 至少 32 位,且至少与 int 一样长
  • long long 至少 64 位,且至少与 long 一样长。
// limits.cpp -- some integer limits
#include <iostream>
#include <climits>              // use limits.h for older systems
int main()
{
    using namespace std;
    int n_int = INT_MAX;        // initialize n_int to max int value
    short n_short = SHRT_MAX;   // symbols defined in climits file
    long n_long = LONG_MAX;
        long long n_llong = LLONG_MAX;

    // sizeof operator yields size of type or of variable
    cout << "int is " << sizeof (int) << " bytes." << endl;
    cout << "short is " << sizeof n_short << " bytes." << endl;
    cout << "long is " << sizeof n_long << " bytes." << endl;
    cout << "long long is " << sizeof n_llong << " bytes." << endl;
    cout << endl;

    cout << "Maximum values:" << endl;
    cout << "int: " << n_int << endl;
    cout << "short: " << n_short << endl;
    cout << "long: " << n_long << endl;
    cout << "long long: " << n_llong << endl << endl;

    cout << "Minimum int value = " << INT_MIN << endl;
    cout << "Bits per byte = " << CHAR_BIT << endl;
        // cin.get();
    return 0;
}

在这里插入图片描述

1.运算符 sizeof 和头文件 limits

可对类型名或变量名使用 sizeof 运算符。对类型名(如 int)使用 sizeof 运算符时,应将名称放在括号中;但对变量名(如 n_short)使用该运算符,括号是可选的

    cout << "int is " << sizeof (int) << " bytes." << endl;
    cout << "short is " << sizeof n_short << " bytes." << endl;

如 INT_MAX 表示类型 int 能够存储的最大值

在这里插入图片描述

climits 中包含符号常量(预处理方式)来表示类型的限制。

#define INT_MAX 32767

2.初始化

初始化将赋值与声明合并在一起。例如,下面的语句声明了变量 n_int,并将 int 的最大取值赋给它:

int n_int = INT_MAX;

也可以使用字面值常量来初始化。可以将变量初始化为另一个变量,条件是后者已经定义过。甚至可以使用表达式来初始化变量,条件是当程序执行到该声明时,表达式中所有的值都是已知的:

int uncles = 5;
int aunts = uncles;
int chairs = aunts + aunts + 4;

如果将 uncles 的声明移到语句列表的最后,则另外两条初始化语句将非法,因为这样当程序试图对其他变量进行初始化时,uncles 的值是未知的。

C++还有另一种 C 语言没有的初始化语法:

int owl = 101;
int wrens(432);

如果不对函数内部定义的变量进行初始化,该变量的值将是不确定的。这意味着该变量的值

将是它被创建之前,相应内存单元保存的值。

如果知道变量的初始值应该是什么,则应对它进行初始化。将变量声明和赋值分开。

short year;
year = 1492;

在声明变量时对它进行初始化,可避免以后忘记给它赋值的情况发生。

3.C++11 初始化方式

还有另一种初始化方式,这种方式用于数组和结构,但在 C++98 中,也可用于单值变量:

int hamburgers = {24};

将大括号初始化器用于单值变量的情形还不多,但 C++11 标准使得这种情形更多了。首先,采用这种方式时,可以使用等号(=),也可以不使用:

int emus{7};
int rheas = {12};

其次,大括号内可以不包含任何东西。在这种情况下,变量将被初始化为零:

int rocs = {};
int psychics{};

3.1.4 无符号类型

要创建无符号版本的基本整型,只需使用关键字 unsigned 来修改声明即可:

unsigned short change;
unsigned int rovert;
unsigned quarterback;
unsigned quarterback;
unsigned long long lang_lang

注意,unsigned 本身是 unsigned int 的缩写。

3.1.4 无符号类型

// exceed.cpp -- exceeding some integer limits
#include <iostream>
#define ZERO 0      // makes ZERO symbol for 0 value
#include <climits>  // defines INT_MAX as largest int value
int main()
{
    using namespace std;
    short sam = SHRT_MAX;     // initialize a variable to max value
    unsigned short sue = sam;// okay if variable sam already defined

    cout << "Sam has " << sam << " dollars and Sue has " << sue;
    cout << " dollars deposited." << endl
         << "Add $1 to each account." << endl << "Now ";
    sam = sam + 1;
    sue = sue + 1; 
    cout << "Sam has " << sam << " dollars and Sue has " << sue;
    cout << " dollars deposited.\nPoor Sam!" << endl;
    sam = ZERO;
    sue = ZERO;
    cout << "Sam has " << sam << " dollars and Sue has " << sue;
    cout << " dollars deposited." << endl;
    cout << "Take $1 from each account." << endl << "Now ";
    sam = sam - 1;
    sue = sue - 1;
    cout << "Sam has " << sam << " dollars and Sue has " << sue;
    cout << " dollars deposited." << endl << "Lucky Sue!" << endl;
        // cin.get();
    return 0; 
}

在这里插入图片描述

该程序将一个 short 变量(sam)和一个 unsigned short 变量(sue)分别设置为最大的 short 值,在我们的系统上,是 32767。然后,将这些变量的值都加 1。这对于 sue 来说没有什么问题,因为新值仍比无符号整数的最大值小得多;但 sam 的值从 32767 变成了−32768!同样,对于 sam,将其设置为 0 并减去 1,也不会有问题;但对于无符号变量 sue,将其设置为 0 并减去后,它变成了 65535。可以看出,这些整型变量的行为就像里程表。如果超越了限制,其值将为范围另一端的取值。C++确保了无符号类型的这种行为;但 C++并不保证符号整型超越限制(上溢和下溢)时不出错,而这正是当前实现中最为常见的行为。

在这里插入图片描述

3.1.5 选择整型类型

C++提供了大量的整型,应使用哪种类型呢?通常,int 被设置为对目标计算机而言最为“自然”的长度。自然长度(natural size)指的是计算机处理起来效率最高的长度。如果没有非常有说服力的理由来选择其他类型,则应使用 int。

3.1.6 整型字面值

// hexoct1.cpp -- shows hex and octal literals
#include <iostream>
int main()
{
    using namespace std;
    int chest = 42;     // decimal integer literal
    int waist = 0x42;   // hexadecimal integer literal
    int inseam = 042;   // octal integer literal

    cout << "Monsieur cuts a striking figure!\n";
    cout << "chest = " << chest << " (42 in decimal)\n";
    cout << "waist = " << waist << " (0x42 in hex)\n";
    cout << "inseam = " << inseam << " (042 in octal)\n";
        // cin.get();
    return 0; 
}

在这里插入图片描述

在默认情况下,cout 以十进制格式显示整数。

// hexoct2.cpp -- display values in hex and octal
#include <iostream>
using namespace std;
int main()
{
    using namespace std;
    int chest = 42;
    int waist = 42; 
    int inseam = 42;

    cout << "Monsieur cuts a striking figure!"  << endl;
    cout << "chest = " << chest << " (decimal for 42)" << endl;
    cout << hex;      // manipulator for changing number base
    cout << "waist = " << waist << " (hexadecimal for 42)" << endl;
    cout << oct;      // manipulator for changing number base
    cout << "inseam = " << inseam << " (octal for 42)" << endl;
    // cin.get();
    return 0; 
}

在这里插入图片描述

如果要以十六进制或八进制方式显示值,则可以使用 cout 的一些特殊特性。前面指出过,头文件 iostream 提供了控制符 endl,用于指示 cout 重起一行。同样,它还提供了控制符 dec、hex 和 oct,分别用于指示 cout 以十进制、十六进制和八进制格式显示整数。

3.1.7 C++如何确定常量的类型

程序的声明将特定的整型变量的类型告诉了 C++编译器,但编译器是如何知道常量的类型呢?

除非有理由存储为其他类型(如使用了特殊的后缀来表示特定的类型,或者值太大,不能存储为 int),否则 C++将整型常量存储为 int 类型。

后缀是放在数字常量后面的字母,用于表示类型。整数后面的 l 或 L 后缀表示该整数为 long 常量,u 或 U 后缀表示 unsigned int 常量,ul(可以采用任何一种顺序,大写小写均可)表示 unsigned long 常量(由于小写 l 看上去像 1,因此应使用大写 L 作后缀)。

3.1.8 char 类型:字符和小整数

char 类型是专为存储字符(如字母和数字)而设计的。

char 类型是另一种整型。它足够长,能够表示目标计算机系统中的所有基本符号—所有的字母、数字、标点符号等。

在美国,最常用的符号集是 ASCII 字符集。字符集中的字符用数值编码(ASCII 码)表示。例如,字符 A 的编码为 65,字母 M 的编码为 77。

// chartype.cpp -- the char type
#include <iostream>
int main( )
{
    using namespace std;
    char ch;        // declare a char variable

    cout << "Enter a character: " << endl;
    cin >> ch;
    cout << "Hola! ";
    cout << "Thank you for the " << ch << " character." << endl;
    // cin.get();
    // cin.get();
    return 0;
}

在这里插入图片描述

程序中输入的是 M,而不是对应的字符编码 77。另外,程序将打印 M,而不是 77。通过查看内存可以知道,77 是存储在变量 ch 中的值。这种神奇的力量不是来自 char 类型,而是来自 cin 和 cout,这些工具为您完成了转换工作。输入时,cin 将键盘输入的 M 转换为 77;输出时,cout 将值 77 转换为所显示的字符 M;cin 和 cout 的行为都是由变量类型引导的。

C++对字符用单引号,对字符串使用双引号。

// morechar.cpp -- the char type and int type contrasted
#include <iostream>
int main()
{
    using namespace std;
    char ch = 'M';       // assign ASCII code for M to ch
    int i = ch;          // store same code in an int
    cout << "The ASCII code for " << ch << " is " << i << endl;

    cout << "Add one to the character code:" << endl;
    ch = ch + 1;          // change character code in ch
    i = ch;               // save new character code in i
    cout << "The ASCII code for " << ch << " is " << i << endl;

    // using the cout.put() member function to display a char
    cout << "Displaying char ch using cout.put(ch): ";
    cout.put(ch);

    // using cout.put() to display a char constant
    cout.put('!');

    cout << endl << "Done" << endl;
        // cin.get();
    return 0;
}

在这里插入图片描述

‘M’表示字符 M 的数值编码,因此将 char 变量 ch 初始化为‘M’,将把 c 设置为 77。然后,程序将同样的值赋给 int 变量 i,这样 ch 和 i 的值都是 77。接下来,cout 把 ch 显示为 M,而把 i 显示为 77。如前所述,值的类型将引导 cout 选择如何显示值。

在 C++中,书写字符常量的方式有多种。对于常规字符(如字母、标点符号和数字),最简单的方法是将字符用单引号括起。这种表示法代表的是字符的数值编码。

有些字符不能直接通过键盘输入到程序中。对于这些字符,C++提供了一种特殊的表示方法—转义序列

在这里插入图片描述

在这里插入图片描述

应该像处理常规字符(如 Q)那样处理转义序列(如\n)。也就是说,将它们作为字符常量时,应用单引号括起;将它们放在字符串中时,不要使用单引号。

// bondini.cpp -- using escape sequences
#include <iostream>
int main()
{
    using namespace std;
    cout << "\aOperation \"HyperHype\" is now activated!\n";
    cout << "Enter your agent code:________\b\b\b\b\b\b\b\b";
    long code;
    cin >> code;
    cout << "\aYou entered " << code << "...\n";
    cout << "\aCode verified! Proceed with Plan Z3!\n";
    // cin.get();
    // cin.get();
    return 0; 
}

在这里插入图片描述

与 int 不同的是,char 在默认情况下既不是没有符号,也不是有符号。是否有符号由 C++实现决定,这样编译器开发人员可以最大限度地将这种类型与硬件属性匹配起来。如果 char 有某种特定的行为对您来说非常重要,则可以显式地将类型设置为 signed char 或 unsigned char。

如果将 char 用作数值类型,则 unsigned char 和 signed char 之间的差异将非常重要。unsigned char 类型的表示范围通常为 0~255,而 signed char 的表示范围为−128 到 127。

C++11 新增了类型 char16_t 和 char32_t,其中前者是无符号的,长 16 位,而后者也是无符号的,但长 32 位。C++11 使用前缀 u 表示 char16_t 字符常量和字符串常量

3.1.9 bool 类型

在计算中,布尔变量的值可以是 true 或 false。然而,现在可以使用 bool 类型来表示真和假了,它们分别用预定义的字面值 true 和 false 表示。

字面值 true 和 false 都可以通过提升转换为 int 类型,true 被转换为 1,而 false 被转换为 0

3.2 const 限定符

使用 const 关键字来修改变量声明和初始化。

const int Months = 12;

常量(如 Months)被初始化后,其值就被固定了,编译器将不允许再修改该常量的值。

如果在声明常量时没有提供值,则该常量的值将是不确定的,且无法修改。

const关键字来修改变量声明和初始化。常量被初始化后,其值就被固定,编译器将不允许再修改该常量的值。

将名称的首字母大写,以便提醒是个常量,可便于阅读性增强。如果是变量名全大写,则使用 #define

3.3 浮点数

浮点类型,它们是 C++的第二组基本类型。浮点数能够表示带小数部分的数字。

浮点数就是表示小数点部分的数字。计算机将值分为两部分存储,一部分表示值,另一部分则用于对值进行放大或缩小。

3.3.1 书写浮点数

C++有两种书写浮点数的方式。第一种是使用常用的标准小数点表示法,第二种表示浮点值的方法叫做 E 表示法。

小数点表示法

12.34

E 表示法

3.45E6,这指的是 3.45 与 1000000 相乘的结果;E6 指的是 10 的 6 次方,即 1 后面 6 个 0。因此,3.45E6 表示的是 3450000,6 被称为指数,3.45 被称为尾数。

E 表示法确保数字以浮点格式存储,即使没有小数点。注意,既可以使用 E 也可以使用 e,指数可以是正数也可以是负数。

在这里插入图片描述

3.3.2 浮点类型

C++也有 3 种浮点类型:float、double 和 long double。

事实上,C 和 C++对于有效位数的要求是,float 至少 32 位,double 至少 48 位,且不少于 float,long double 至少和 double 一样多。

这三种类型的有效位数可以一样多。然而,通常,float 为 32 位,double 为 64 位,long double 为 80、96 或 128 位。另外,这 3 种类型的指数范围至少是−37 到 37。可以从头文件 cfloat 或 float.h 中找到系统的限制。

// floatnum.cpp -- floating-point types
#include <iostream>
int main()
{
    using namespace std; 
    cout.setf(ios_base::fixed, ios_base::floatfield); // fixed-point
    float tub = 10.0 / 3.0;     // good to about 6 places
    double mint = 10.0 / 3.0;   // good to about 15 places
    const float million = 1.0e6;

    cout << "tub = " << tub;
    cout << ", a million tubs = " << million * tub;
    cout << ",\nand ten million tubs = ";
    cout << 10 * million * tub << endl;

    cout << "mint = " << mint << " and a million mints = ";
    cout << million * mint << endl;
    // cin.get();
    return 0;
}

在这里插入图片描述

3.3.3 浮点常量

在程序中书写浮点常量的时候,程序将把它存储为哪种浮点类型呢?在默认情况下,像 8.24 和 2.4E8 这样的浮点常量都属于 double 类型。如果希望常量为 float 类型,请使用 f 或 F 后缀。对于 long double 类型,可使用 l 或 L 后缀(由于 l 看起来像数字 1,因此 L 是更好的选择)。

3.3.4 浮点数的优缺点

与整数相比,浮点数有两大优点。首先,它们可以表示整数之间的值。其次,由于有缩放因子,它们可以表示的范围大得多。另一方面,浮点运算的速度通常比整数运算慢,且精度将降低。

// fltadd.cpp -- precision problems with float
#include <iostream>
int main()
{
    using namespace std;
    float a = 2.34E+22f;
    float b = a + 1.0f;

    cout << "a = " << a << endl;
    cout << "b - a = " << b - a << endl;
    // cin.get();
    return 0; 
}

在这里插入图片描述

2.34E+22 是一个小数点左边有 23 位的数字。加上 1,就是在第 23 位加 1。但 float 类型只能表示数字中的前 6 位或前 7 位,因此修改第 23 位对这个值不会有任何影响。

3.4 C++算术运算符

五种基本运算符进行基本的算术运算。

加(+)、减(-)、乘(*)、除(/)、求模(%)

运算符的优先级和数学中的优先级类似。

// arith.cpp -- some C++ arithmetic
#include <iostream>
int main()
{
    using namespace std;
    float hats, heads;

    cout.setf(ios_base::fixed, ios_base::floatfield); // fixed-point
    cout << "Enter a number: ";
    cin >> hats;
    cout << "Enter another number: ";
    cin >> heads;

    cout << "hats = " << hats << "; heads = " << heads << endl;
    cout << "hats + heads = " << hats + heads << endl;
    cout << "hats - heads = " << hats - heads << endl;
    cout << "hats * heads = " << hats * heads << endl;
    cout << "hats / heads = " << hats / heads << endl;
    // cin.get();
    // cin.get();
    return 0;
}

在这里插入图片描述

11.17 加上 50.25 应等于 61.42,但是输出中却是 61.419998。这不是运算问题;而是由于 float 类型表示有效位数的能力有限。记住,对于 float,C++只保证 6 位有效位。如果将 61.419998 四舍五入成 6 位,将得到 61.4200,这是保证精度下的正确值。如果需要更高的精度,请使用 double 或 long double。

3.4.1 运算符优先级和结合性

当多个运算符可用于同一个操作数时,C++使用优先级规则来决定首先使用哪个运算符。算术运算符遵循通常的代数优先级,先乘除,后加减。

3.4.2 除法分支

除法运算符(/)的行为取决于操作数的类型。如果两个操作数都是整数,则 C++将执行整数除法。这意味着结果的小数部分将被丢弃,使得最后的结果是一个整数。如果其中有一个(或两个)操作数是浮点值,则小数部分将保留,结果为浮点数。

// divide.cpp -- integer and floating-point division
#include <iostream>
int main()
{
    using namespace std;
    cout.setf(ios_base::fixed, ios_base::floatfield);
    cout << "Integer division: 9/5 = " << 9 / 5  << endl;
    cout << "Floating-point division: 9.0/5.0 = ";
    cout << 9.0 / 5.0 << endl;
    cout << "Mixed division: 9.0/5 = " << 9.0 / 5  << endl;
    cout << "double constants: 1e7/9.0 = ";
    cout << 1.e7 / 9.0 <<  endl;
    cout << "float constants: 1e7f/9.0f = ";
    cout << 1.e7f / 9.0f <<  endl;
    // cin.get();
    return 0;
}

在这里插入图片描述

实际上,对不同类型进行运算时,C++将把它们全部转换为同一类型。本章稍后将介绍这种自动转换。最后两行的相对精度表明,如果两个操作数都是 double 类型,则结果为 double 类型;如果两个操作数都是 float 类型,则结果为 float 类型。记住,浮点常量在默认情况下为 double 类型。

在这里插入图片描述

3.4.3 求模运算符

比起求模运算符来说,多数人更熟悉加、减、乘、除,因此这里花些时间介绍这种运算符。求模运算符返回整数除法的余数。

// modulus.cpp -- uses % operator to convert lbs to stone
#include <iostream>
int main()
{
    using namespace std;
    const int Lbs_per_stn = 14;
    int lbs;

    cout << "Enter your weight in pounds: ";
    cin >> lbs;
    int stone = lbs / Lbs_per_stn;      // whole stone
    int pounds = lbs % Lbs_per_stn;     // remainder in pounds
    cout << lbs << " pounds are " << stone
         << " stone, " << pounds << " pound(s).\n";
    // cin.get();
    // cin.get();
    return 0; 
}

在这里插入图片描述

在表达式 lbs/Lbs_per_stn 中,两个操作数的类型都是 int,所以计算机执行整数除法。

3.4.4 类型转换

类型转换的规则

  • 将一种算术类型的值赋给另一种算术类型的变量时,C++对值转换为接收变量的类型。
  • 表达式中包含不同的类型时,C++对值进行转换
  • 将参数传递给函数时,由函数原型控制,C++对值进行转换

数值转换中存在的潜在问题

1.初始化和赋值进行的转换

C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换为接收变量的类型。

将一个值赋给值取值范围更大的类型通常不会导致什么问题。例如,将 short 值赋给 long 变量并不会改变这个值,只是占用的字节更多而已。然而,将一个很大的 long 值(如 2111222333)赋给 float 变量将降低精度。

将 0 赋给 bool 变量时,将被转换为 false;而非零值将被转换为 true。

将浮点值赋给整型将导致两个问题。首先,将浮点值转换为整型会将数字截短(除掉小数部分)。

// assign.cpp -- type changes on assignment
#include <iostream>
int main()
{
    using namespace std;
    cout.setf(ios_base::fixed, ios_base::floatfield);
    float tree = 3;     // int converted to float
    int guess = 3.9832; // float converted to int
    int debt = 7.2E12;  // result not defined in C++
    cout << "tree = " << tree << endl;
    cout << "guess = " << guess << endl;
    cout << "debt = " << debt << endl;
    // cin.get();
    return 0;
}

在这里插入图片描述
%2F1722154677245-16.png&pos_id=img-zs8m7f8L-1722154771512)

在这个程序中,将浮点值 3.0 赋给了 tree。将 3.9832 赋给 int 变量 guess 导致这个值被截取为 3。将浮点型转换为整型时,C++采取截取(丢弃小数部分)而不是四舍五入(查找最接近的整数)。最后,int 变量 debt 无法存储 3.0E12,这导致 C++没有对结果进行定义的情况发生。在这种系统中,debt 的结果为 1634811904,或大约 1.6E09。当您将整数变量初始化为浮点值时,有些编译器将提出警告,指出这可能丢掉数据。另外,对于 debt 变量,不同编译器显示的值也可能不同。例如,在另一个系统上运行该程序时,得到的值为 2147483647。

2.以{ }方式初始化时进行的转换(C++11)

C++11 将使用大括号的初始化称为列表初始化(listinitialization),因为这种初始化常用于给复杂的数据类型提供值列表。它对类型转换的要求更严格。具体地说,列表初始化不允许缩窄(narrowing),即变量的类型可能无法表示赋给它的值。

3.表达式中的转换

当同一个表达式中包含两种不同的算术类型时,将出现什么情况呢?

在这种情况下,C++将执行两种自动转换:首先,一些类型在出现时便会自动转换;其次,有些类型在与其他类型同时出现在表达式中时将被转换。

(1)如果有一个操作数的类型是 long double,则将另一个操作数转换为 long double。

(2)否则,如果有一个操作数的类型是 double,则将另一个操作数转换为 double。

(3)否则,如果有一个操作数的类型是 float,则将另一个操作数转换为 float。

(4)否则,说明操作数都是整型,因此执行整型提升。

(5)在这种情况下,如果两个操作数都是有符号或无符号的,且其中一个操作数的级别比另一个低,则转换为级别高的类型。

(6)如果一个操作数为有符号的,另一个操作数为无符号的,且无符号操作数的级别比有符号操作数高,则将有符号操作数转换为无符号操作数所属的类型。

(7)否则,如果有符号类型可表示无符号类型的所有可能取值,则将无符号操作数转换为有符号操作数所属的类型。

(8)否则,将两个操作数都转换为有符号类型的无符号版本。

4.传递参数时的转换

传递参数时的类型转换通常由 C++函数原型控制。然而,也可以取消原型对参数传递的控制,尽管这样做并不明智。在这种情况下,C++将对 char 和 short 类型(signed 和 unsigned)应用整型提升。另外,为保持与传统 C 语言中大量代码的兼容性,在将参数传递给取消原型对参数传递控制的函数时,C++将 float 参数提升为 double。

5.强制类型转换

C++还允许通过强制类型转换机制显式地进行类型转换。(C++认识到,必须有类型规则,而有时又需要推翻这些规则。)强制类型转换的格式有两种。例如,为将存储在变量 thorn 中的 int 值转换为 long 类型。

强制转换本身不会修改变量本身,而是创建一个新的、指定类型的值

强制转换的通用格式如下:

(typename) value //来源于C语言
typename (value) // C++
// typecast.cpp -- forcing type changes
#include <iostream>
int main()
{
    using namespace std;
    int auks, bats, coots;

    // the following statement adds the values as double,
    // then converts the result to int
    auks = 19.99 + 11.99;

    // these statements add values as int
    bats = (int) 19.99 + (int) 11.99;   // old C syntax
    coots = int (19.99) + int (11.99);  // new C++ syntax
    cout << "auks = " << auks << ", bats = " << bats;
    cout << ", coots = " << coots << endl;

    char ch = 'Z';
    cout << "The code for " << ch << " is ";    // print as char
    cout << int(ch) << endl;                    // print as int
    cout << "Yes, the code is ";
    cout << static_cast<int>(ch) << endl;       // using static_cast
   // cin.get();
    return 0; 
}

在这里插入图片描述

首先,将 19.99 和 11.99 相加,结果为 31.98。将这个值赋给 int 变量 auks 时,它被截短为 31。但在进行加法运算之前使用强制类型转换时,这两个值将被截短为 19 和 11,因此 bats 和 coots 的值都为 30。接下来,两条 cout 语句使用强制类型转换将 char 类型的值转换为 int,再显示它。这些转换导致 cout 将值打印为整数,而不是字符。

3.4.5 C++11 中的 auto 声明

在初始化声明中,如果使用关键字auto 时,而不指定变量的类型,编译器将把变量的类型设置成与初始值相同。

auto n = 100; /*自动设置为int类型*/
auto x = 1.15; /*自动设置为double类型*/

3.5 总结

C++的基本类型分为两组:一组由存储为整数的值组成,另一组由存储为浮点格式的值组成。整型之间通过存储值时使用的内存量及有无符号来区分。整型从最小到最大依次是:bool、char、signed char、unsigned char、short、unsigned short、int、unsigned int、long、unsigned long 以及 C++11 新增的 long long 和 unsigned long long。还有一种 wchar_t 类型,它在这个序列中的位置取决于实现。C++11 新增了类型 char16_t 和 char32_t,它们的宽度足以分别存储 16 和 32 位的字符编码。C++确保了 char 足够大,能够存储系统基本字符集中的任何成员,而 wchar_t 则可以存储系统扩展字符集中的任意成员,short 至少为 16 位,而 int 至少与 short 一样长,long 至少为 32 位,且至少和 int 一样长。确切的长度取决于实现。

字符通过其数值编码来表示。I/O 系统决定了编码是被解释为字符还是数字。

浮点类型可以表示小数值以及比整型能够表示的值大得多的值。3 种浮点类型分别是 float、double 和 long double。C++确保 float 不比 double 长,而 double 不比 long double 长。通常,float 使用 32 位内存,double 使用 64 位,long double 使用 80 到 128 位。

通过提供各种长度不同、有符号或无符号的类型,C++使程序员能够根据特定的数据要求选择合适的类型。

C++使用运算符来提供对数字类型的算术运算:加、减、乘、除和求模。当两个运算符对同一个操作数进行操作时,C++的优先级和结合性规则可以确定先执行哪种操作。

对变量赋值、在运算中使用不同类型、使用强制类型转换时,C++将把值从一种类型转换为另一种类型。很多类型转换都是“安全的”,即可以在不损失和改变数据的情况下完成转换。例如,可以把 int 值转换为 long 值,而不会出现任何问题。对于其他一些转换,如将浮点类型转换为整型,则需要更加小心。

开始,读者可能觉得大量的 C++基本类型有些多余,尤其是考虑到各种转换规则时。但是很可能最终将发现,某些时候,只有一种类型是需要的,此时您将感谢 C++提供了这种类型。

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值