1. C++ 数据类型分类
C++数据类型 = {内置类型(built-in C++ types)} + {拓展类型(Eg:C++11’s additions)}
内置类型 (built-in C++ types) | 类型说明 |
---|---|
基本类型(fundamental types) | 内置整型( built-in integer types),内置浮点型( built-in floating-point) |
组合类型( compound types) | 数组(arrays), 字符串(strings), 指针(pointers)结构体(structures) |
拓展类型 | 类型说明 |
---|---|
C++ 11 扩展 | unsigned long long ,long long |
… | … |
-
内置整型( built-in integer types)
内置整型( built-in integer types) = { unsigned long, long, unsigned int, int, unsigned short, short, char, unsigned char, signed char, bool}整型定义:
A short integer is at least 16 bits wide.
An int integer is at least as big as short.
A long integer is at least 32 bits wide and at least as big as int.
A long long integer is at least 64 bits wide and at least as big as long.注:意味着integer types 不一定包含指定的bits — 待拓展
-
内置浮点型( built-in floating-point)
待办
2. C++ 数据类型操作
一般意义上讲,一个字节(byte)包含8位(bits),但现实情况不一定
一般意义上讲,一个整型 (int)包含4个字节,但现实情况不一定如此。
何况,基本类型包含符号数和无符号数,那么每一种基本类型可以表示数的范围是多少呢? 编程计算过程中如何避免计算溢出呢?
2.1 内置整数类型
2.1.1 整数类型与其有效范围
每一个发型的操作系统,数据类型信息被记录到limits.h(老式操作系统)或者 climits 头文件中
#include <iostream>
using namespace std;
#include <climits>
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;
return 0;
}
- climits 说明
CHAR_MAX | Maximum char value |
CHAR_MIN | Minimum char value |
SCHAR_MAX | Maximum signed char value |
SCHAR_MIN | Minimum signed char value |
UCHAR_MAX | Maximum unsigned char value |
SHRT_MAX | Maximum short value |
SHRT_MIN | Minimum short value |
USHRT_MAX | Maximum unsigned short value |
INT_MAX | Maximum int value |
INT_MIN | Minimum int value |
UINT_MAX | Maximum unsigned int value |
LONG_MAX | Maximum long value |
LONG_MIN | Minimum long value |
ULONG_MAX | Maximum unsigned long value |
LLONG_MAX | Maximum long long value |
LLONG_MIN | Minimum long long value |
ULLONG_MAX | Maximum unsigned long long value |
2.1.2 整数类型与其常数
#include <iostream>
using namespace std;
#include <climits>
#define ZERO 0 // makes ZERO symbol for 0 value
int main()
{
int sam = 34;
cout << "Sam has " << sam <<endl;
sam = -34;
cout << "Sam has " << sam <<endl;
sam = 0x22;
cout << "Sam has " << sam <<endl;
sam = -0x22;
cout << "Sam has " << sam <<endl;
sam = 042;
cout << "Sam has " << sam <<endl;
sam = -042;
cout << "Sam has " << sam <<endl;
return 0;
}
可以使用十进制 八进制 或者 十六进制(有符号或者无符号)
2.1.3 整数类型的计算与溢出
#include <iostream>
using namespace std;
#include <climits>
#define ZERO 0 // makes ZERO symbol for 0 value
int main()
{
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;
return 0;
}
Sam has 32767 dollars and Sue has 32767 dollars deposited. Add $1 to
each account.
Now Sam has -32768 dollars and Sue has 32768 dollars
deposited.
Poor Sam! Sam has 0 dollars and Sue has 0 dollars deposited.
Take $1 from each account.
Now Sam has -1 dollars and Sue has 65535
2.1.4 整数类型的溢出和规避
- 无符号数
运算类型 | 溢出类型 | 判断没有溢出 | 注意 |
---|---|---|---|
s=x+y | 可能上溢 | s≥x | 不能使用s-x==y来判断 |
s=x-y | x<y时会下溢 | x>=y | NA |
m=x*y | 可能上溢 (x0&&m0) | (x!=0&&m/x==y) NA | |
m=x/y | 不会溢出 | 1==1 | NA |
- 有符号数
运算类型 | 溢出类型 | 如何判断不溢出 | 注意 |
s=x+y | 可能上溢或下溢 | !((x>=0&&y>=0&&s<0)||(x<0&&y<0&&s>=0)) | NA |
s=x-y | 可能上溢或下溢 | !((x<0&&y>0&&s>=0)||(x>0&&y<0&&s<=0)) | NA |
m=x*y | 可能上溢 | !x ||m/x==y | NA |
m=x/y | 不会溢出 | NA | NA |
参考资料:
https://blog.csdn.net/EasonDongH/article/details/86572335
2.1.5 特殊的整数类型 char、wchar_t
-
目的
char 类型用于对字符进行编码,而字符用于文字编码 -
类型
-
char 最常见的是我们常说的ASCII码!( United States is the ASCII character set),由8bits构成
-
wchar_t 是国际编码(Unicode), 通常为2个byte,表示字符更多
#include <iostream> using namespace std; #include <climits> #define ZERO 0 // makes ZERO symbol for 0 value int main() { wchar_t bob = L'P'; // a wide-character constant wcout << bob << endl; wcout << L"tall" << endl; // outputting a wide-character string return 0; }
-
char16_t and char32_t
同样属于Unicode,不过编码又有所不同。wcout 打印不出来的
-
2.2 内置浮点类型
2.2.1 浮点数编码
-
浮点数编码参考
https://blog.csdn.net/qq_41694201/article/details/83476003 -
浮点数类型示例
//float, double,and long double #include <iostream> using namespace std; #include <climits> int main() { float f = 12.34; //a double constant f = 1.234f; // a float constant f = 2.45E20F; // a float constant f =2.345324E28; // a double constant f = 2.2L; // a long double constant f = 939001.32; // floating-point f = 0.00023; // floating-point f = 8.0; // still floating-point f = 2.52e+8; // can use E or e, + is optional f = 8.33E-4; // exponent can be negative f = 7E5; // same as 7.0E+05 f = -18.32e1; // can have + or - sign in front f = 1.69e12; // 2010 Brazilian public debt in reais f = 5.98E24; // mass of earth in kilograms f = 9.11e-31; // mass of an electron in kilograms return 0; }
2.2.2 浮点数精度
- 尾数的位数 决定了浮点数表示精度
- 幂数的位数 决定了浮点数表示范围
每一台计算机的浮点数编码格式不一定完全一致,浮点编码信息被写入到cfloat 或者 float.h 的头文件
有效位的位数最小承诺值(转换为10进制后)
// the following are the minimum number of significant digits
#define DBL_DIG 15 // double
#define FLT_DIG 6 // float
#define LDBL_DIG 18 // long double
尾数的编码位数,浮点类型尾数决定了精度(二进制位)
// the following are the number of bits used to represent the mantissa
#define DBL_MANT_DIG 53
#define FLT_MANT_DIG 24
#define LDBL_MANT_DIG 64
指数的范围,数量的量级(十进制)
// the following are the maximum and minimum exponent values
#define DBL_MAX_10_EXP +308
#define FLT_MAX_10_EXP +38
#define LDBL_MAX_10_EXP +4932
#define DBL_MIN_10_EXP -307
#define FLT_MIN_10_EXP -37
#define LDBL_MIN_10_EXP -4931
2.2.3 浮点数的问题
2.2.3.1 浮点打印
#include <iostream>
#include <iomanip>
#include <cfloat>
using namespace std;
int main()
{
cout.setf(ios_base::fixed, ios_base::floatfield); // fixed-point
float fmint = 10.0/3.0;
double dmint = 10.0/3.0;
cout<<setprecision(LDBL_DIG)<<fmint<<endl;
cout<<setprecision(LDBL_DIG)<<dmint<<endl;
cout << endl;
cout<<setprecision(DBL_DIG)<<fmint<<endl;
cout<<setprecision(DBL_DIG)<<dmint<<endl;
cout << endl;
cout<<setprecision(FLT_DIG)<<fmint<<endl;
cout<<setprecision(FLT_DIG)<<dmint<<endl;
return 0;
}
output: 可见,float 只能保证6位精度,double 只能保证15位精度
3.333333253860473633
3.333333333333333481
3.333333253860474
3.333333333333333
3.333333
3.333333
2.2.3.2 精度问题
2.3.3.2.1 加法运算结果无法精确表示
#include <iostream>
using namespace std;
#include <climits>
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;
return 0;
}
outPut: 50.25 + 11.17 = 61.42,但是这里加减法结果却得到了近似数
Enter a number: 50.25
Enter another number: 11.17
hats = 50.250000; heads = 11.170000
hats + heads = 61.419998
hats - heads = 39.080002
hats * heads = 561.292480
hats / heads = 4.498657
2.2.3.2.2 加法运算结果导致部分被舍
#include <iostream>
using namespace std;
#include <climits>
int main()
{
float a = 2.34E+22f;
float b = a + 1.0f;
cout << "a = " << a << endl;
cout << "b - a = " << b - a << endl;
return 0;
}
a = 2.34e+22 b - a = 0
?1.0f
2.2.3.2.3 浮点数的比较运算
参考资料:
http://www.fomalhaut.cn/405
2.3 内置组合类型
参考连接:
2.3.1 数组类型
模板 typeName arrayName[arraySize];
#include <iostream>
int main()
{
//set vals for members
using namespace std;
int yams[3]; // creates array with three elements
yams[0] = 7; // assign value to first element
yams[1] = 8;
yams[2] = 6;
//initialize all
int yamcosts[3] = {20, 30, 5}; // create, initialize array
//If you partially initialize an array, the compiler sets the remaining elements to zero
float hotelTips[5] = {5.0, 2.5};
//if you do this , all members set to 0
long totals[500] = {0};
//there are 4 members for this array.
short things[] = {1, 5, 3, 8};
//how many things for this array?
int num_elements = sizeof things / sizeof (short);
return 0;
}
2.3.2 字符串类型
//string end has a '\0'
char dog[8] = { 'b', 'e', 'a', 'u', 'x', ' ', 'I', 'I'}; // not a string!
char cat[8] = {'f', 'a', 't', 'e', 's', 's', 'a', '\0'}; // a string!
//better way to make the string
char bird[11] = "Mr. Cheeps"; // the \0 is understood
//oh, may best to make string this way
char fish[] = "Bubbles"; // let the compiler count
2.3.3 结构体类型
// structur.cpp -- a simple structure
#include <iostream>
struct inflatable // structure declaration
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable guest =
{
"Glorious Gloria", // name value
1.88, // volume value
29.99 // price value
}; // guest is a structure variable of type inflatable
// It's initialized to the indicated values
inflatable pal =
{
"Audacious Arthur",
3.12,
32.99
}; // pal is a second variable of type inflatable
// NOTE: some implementations require using
// static inflatable guest =
cout << "Expand your guest list with " << guest.name;
cout << " and " << pal.name << "!\n";
// pal.name is the name member of the pal variable
cout << "You can have both for $";
cout << guest.price + pal.price << "!\n";
return 0;
}
// arrstruc.cpp -- an array of structures
#include <iostream>
struct inflatable
{
char name[20];
float volume;
double price;
};
int main()
{
148 Chapter 4 Compound Types
using namespace std;
inflatable guests[2] = // initializing an array of structs
{
{"Bambi", 0.5, 21.99}, // first structure in array
{"Godzilla", 2000, 565.99} // next structure in array
};
cout << "The guests " << guests[0].name << " and " << guests[1].name
<< "\nhave a combined volume of "
<< guests[0].volume + guests[1].volume << " cubic feet.\n";
return 0;
}
2.3.4 联合类型
2.3.4.1 一般定义
union 用于表示一个内存块,内存大小为size最大的成员
union传统用法,用来定义数据类型
//union_01.cpp
#include <cstdio>
union U{
char c[4];
int x;
};
int main (void)
{
union U v;
v.x =0x11223344;
printf("%#x %#x %#x %#x",v.c[0],v.c[1],v.c[2],v.c[3]);
printf(" &int = %p, &array = %p\n",&v.x, v.c);
return 0;
}
2.3.4.2 使用价值
结构体tagPacket 描述了一个内存块,这个内存块确切来讲是一个容器。你可以把 STRUCTTYPE1 STRUCTTYPE2 STRUCTTYPE3 STRUCTTYPE4 , 四种类型数据直接拷贝进来,然后根据pktType字段进行区别处理
typedef unsigned char BYTE;
//报文内容联合体
typedef union tagPacketContent
{
STRUCTTYPE1 pkt1;
STRUCTTYPE2 pkt2;
STRUCTTYPE3 pkt1;
STRUCTTYPE4 pkt2;
}PacketContent;
//统一的报文数据结构
typedef struct tagPacket
{
BYTE pktType;
PacketContent pktContent;
}Packet;
2.3.5 枚举类型
枚举类型按照理解 类型的字面值应当限定在我们需要的那么几种,但是C编译器可以对枚举类型变量随意赋值!!!,这一点在C++是禁止的。
附注:enum.c 使用Gcc 编译顺利通过
// enum.c
enum Items {
a,b,c,d,e
};
int main (void)
{
enum Items i;
i = 10;
return 0;
}
附注:enum.cpp 使用G++ 编译器编译失败
// enum.cpp
#include <iostream>
using namespace std;
enum Items {
a,b,c,d,e
};
int main (void)
{
enum Items i;
i = 10;
return 0;
}
C++允许如下语法,因为枚举类型必为整型
// enum.cpp
#include <iostream>
using namespace std;
enum Items {
a,b,c,d,e
};
enum {UP=0,DOWN=1,LFS=2,RHS=3};
int main (void)
{
enum Items i;
int tmp = i;
cout << e <<endl;
cout <<DOWN <<endl;
return 0;
}
2.3.6 引用类型
C语言指针的使用给编程带来自由的同时,也产生相当的编程风险
C++基于风险考虑,引入了引用类型。引用本质上是C指针
1、 引用 即 变量别名,一但被初始化(和变量绑定),该引用变量就相当于该变量
#include <iostream>
int main()
{
using namespace std;
int a = 100;
int& b = a;
cout << a << ' ' << b << endl; //100 100
b = 99;
cout << a << ' ' << b << endl; //99 99
return 0;
}
2、引用和函数
下面的加法有效改变调用者使用的变量,减法对调用者变量没有影响
#include <iostream>
using namespace std;
void inc(int& a)
{
a++;
}
void dec(int b)
{
b--;
}
int main(void)
{
int x = 99;
inc(x);
cout << "x after inc : " << x << endl;
dec(x);
cout << "x after dec: " << x << endl;
return 0;
}