内置的C++数据类型分为两类:基本类型与复合类型。本章介绍基本类型及其变体。
3.1简单变量
变量名实际上是程序标记存放数据的内存的名称,C++中变量名的命名规则:
·只能使用字母字符、数字、下划线;
·第一个字符不能为数字;
·C++区分大小写;
·下划线开头的变量由保留实现(第四章详解);
3.2整形变量及类别
整形变量有char,int,short,long,longlong,每种都分为有符号与无符号。
在新的标准钟,每种类型确保最小长度: (1 byte = 8 bit) 1位=8字节
short 16 bit int 32 bit long 32 bit longlong 64 bit;
int可以选择为16 or 24 or 32 or 64;
/*******************************************/
// 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;
}
头文件limits定义了各种限制的符号名称。
sizeof可以获取变量的字节长度(byte),对类型名使用时需要(),对变量名使用时不需要。
变量的初始化有三种方式:直接初始化,间接初始化(用变量初始化变量),运算初始化。
/*******************************************/
// 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;
}
关于无符号类型运行以上代码便可知其大概。
/*******************************************/
// 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;
}
该段代码是将42对应的十进制、十六进制、八进制用十进制表示。
// 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<<控制符(dec,hex,oct) 可以指示cout以什么进制显示整数。
关于cout,显示数据时,若无特殊的后缀(L or l ; U or u ; UL or Ul or uL or ul ;LL ; ULL)或数值太大无法使用int,则通常将整形数据存储为int。
/*******************************************/
// 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;
}
char类型用于存储字母,一个字节大小(1byte=8bit),对应ASCII码,关于如何显示char类型变量的ASCII值可以看下面的程序:
// 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;
}
char默认情况下不是无符号也不是有符号,可以显示设置。
宽字符类型wcahr_t有足够的空间,对应使用wcin与wcout。(涉及到时会补充)
···bool类型···
true 1 false 0
3.2 const限定符
使用const限定符可以定义常量,即不可修改的变量。(关于全部变量将在后面介绍)
3.3 浮点数
浮点数可以表示带小数部分的数字,表示范围也比整形更大。
浮点数的表示方法分为小数点表示法与科学计数表示法。
// 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;
}
浮点数分为三种类型:float 、double 、 long double
cout会删除浮点数结尾的0,而cout.setf()则不会。
在定义浮点数常量时,使用后缀可以指定浮点数的类型: f F l L ,默认为double。
// 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;
}
浮点数在运算时精度会降低,并且运行慢。关于精度问题可以参考算法竞赛入门这本书。
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;
}
四则运算,乘除的优先级比加减高,两两平级时看结合性(涉及到自定义操作时,对于四则而言都是自左向右)。
// 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;
}
除法运算则与变量类型相关,精度问题是除法的关注点。
// 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;
}
求模运算的操作数必须是整形,若是浮点数则会出错。、
若操作数存在负数,则符号满足(a/b)*b+a%b = a关系式。
3.5 类型转换
在对不同类型的变量进行运算时,会出现精度丢失等情况,为此C++内置有三种转换:
将一种算数类型的值赋值给另一种算数类型的变量时;
表达式中包含不同的类型时;
将参数传递给函数时。
/*****初始化和赋值进行的转换******/
C++允许将一种类型的值赋给另一种类型的变量,值将转换为接受变量的类型
short thirty=12;
long big = thirty;
但是从小范围转化为大范围通常没有问题,但是从大范围转化为小范围是会丢失数据(详情参考计算机组成结构).
// 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;
}
运行之后就知道结果。
/********以{}方式初始化进行的转换********/
列表初始化通常用于为复杂的数据类型提供值列表,不允许缩窄narrowing,即变量的类型可能无法表示赋给它的值。EG:不允许将浮点数转换为整形等。(交代很少)
/*******表达式中的转换******/
将不同的类型进行算术运算时,涉及到两种数据类型时,较小转换为较大。
C++11版本校验表:
·if 一个数为long double类型,则将另一个也转换。
·else if 有一个为double,则另一个也转换。
·else if 有一个为float,则另一个也转换。
·else 都为整形,则执行整形提升
·在上述情况下,若两个操作数都是有符号或都是无符号,且一低一高,则转化为高。
·若一个无符号一个有符号,且无符号比有符号高,则有符号数转换为无符号数的类型。
·否则,若有符号类型可表示无符号类型的所有可能值(根据limits头文件可以判断出来,C++内置也可以),则将无符号数转换为有符号操作数。
·否则就将两个操作数都转换为有符号类型的无符号版本。
/*******传递参数时的转换*******/
C++原型函数控制下,char与short类型会进行整形提升,float提升为double
/*******强制类型转换**********/
// 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;
}
由上述代码可以认识到在运算中数据存放与赋值的关系。