char | short | int | long | float | double | 指针 | |
---|---|---|---|---|---|---|---|
32位系统字节数 | 1(8) | 2(16) | 4(32) | 4(32) | 4(32) | 8(64) | 4(32) |
64位系统字节数 | 1(8) | 2(16) | 4(32) | 8(32) | 4(32) | 8(64) | 8(64) |
字数 | 一个字 | 一个字 | 两个字 | ||||
有效位 | 0 | 7 | 16 | ||||
最大值 | 42 9496 7296 | **** |
注:内存Buffer运算一般以字节为单位;上述字数转换使用一个字=四个字节
符号位s | 指数位E 是有符号的 比较特殊,需要移位 | 尾数位M 只是小数点后面的位数哈 | |
---|---|---|---|
float | 1 | 8 (-127~128) | 23 |
double | 1 | 11 (-1023~1024) | 52 |
表示方法:(-1)^ S*1.M *2^E
这里的E是十进制的哈。
精度
float: -2^ 128~2^128=-3.40E+38 ~ +3.40E+38
double:-2^ 1024~2^1025=-1.79E+308 ~ +1.79E+308
有效位
2^23=838,8608(7位,但是最后一位由于四舍五入不一定准确,所以精确度6位肯定是准确的)
2^52=4503,5996,2737,0496(16位,但是最后一位由于四舍五入不一定准确,所以精确度15位肯定是准确的)
参考链接
if(i) VS if(i == true)
if(!i) VS if(i == false)
#include <iostream>
using namespace std;int main()
{for(int i = -5; i <= 5; i++){if(i == true){cout << i << " == true" << endl;}else if(i == false){cout << i << " == false" << endl;}else{cout << i << " wrong!" << endl;}}cout << endl;for(int i = -5; i <= 5; i++){if(i){cout << i << " true" << endl;}else if(!i){cout << i << " false" << endl;}else{cout << i << " wrong!" << endl;}}}
输出如下
-5 wrong!
-4 wrong!
-3 wrong!
-2 wrong!
-1 wrong!
0 == false
1 == true
2 wrong!
3 wrong!
4 wrong!
5 wrong!-5 true
-4 true
-3 true
-2 true
-1 true
0 false
1 true
2 true
3 true
4 true
5 true
#include <iostream>
using namespace std;int main()
{// 1.1 char to int(real)cout << "char to int(real): [int(x)] " <<endl;char a1 = 'n';char a2 = 'r';int ia1 = (int)a1; int ia2 = (int)a2; /* note that the int cast is not necessary -- int ia = a would suffice */cout << "\n(换行): " << ia1 << endl;cout << "\r(回车): " << ia2 << endl << endl;// 1.2 char to int(superficial)cout << "char to int(superficial): [x - '0']"<<endl;char b = '0';int ib = b - '0';cout << "‘0’: " << ib << endl << endl;/* check here if ia is bounded by 0 and 9 */// 2. char to Hexadecimal(0x,real)cout << "char to Hexadecimal(0x,real):[sprintf(str, "%x", 'a')]" <<endl;char str[255] = {0}; sprintf(str, "%x", 'a'); //将100转为16进制表示的字符串。cout << "str:" << str << endl;cout << "the size of str:" << sizeof(str) / sizeof(char) << endl;string ss(str);cout << "ss:" << ss << endl;cout << "ss.size():" << ss.size() << endl;return 0;
}
输出如下:
char to int(real): [int(x)]
n(换行): 10
r(回车): 13char to int(superficial): [x - '0']
‘0’: 0char to Hexadecimal(0x,real):[sprintf(str, "%x", 'a')]
str:61
the size of str:255
ss:61
ss.size():2
Binary | 00000000 | 00000001 | … | 01111111 | 10000000 | 10000001 | … | 11111100 | 11111110 | 11111111 |
signed | 0 | 1 | … | 127 | -128 | -127 | … | -3 | -2 | -1 |
unsigned | 0 | 1 | … | 127 | 128 | 129 | … | 253 | 254 | 255 |
十进制 | 0 | 1 | 2 | 3 | … | 127 | -128 | -127 | … | -3 | -2 | -1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
原码 | 00000000 | 00000001 | 00000002 | 00000003 | … | 01111111 | 10000000 | 11111111 | … | 10000011 | 10000010 | 10000001 |
反码 (除符号位取反) | 00000000 | 00000001 | 00000002 | 00000003 | … | 01111111 | 11111111 | 10000000 | … | 111111100 | 11111101 | 11111110 |
补码 (反码+1) | 00000000 | 00000001 | 00000002 | 00000003 | … | 01111111 | 10000000 | 10000001 | … | 11111101 | 11111110 | 11111111 |
unsigned | 0 | 1 | 2 | 3 | … | 127 | 128 | 129 | … | 253 | 254 | 255 |
C++标准中并没有规定带符号数类型如何表示,
但规定了在表示范围内正值与负值的量应该均衡。
因此,8比特的signed char理论上应该表示-127~127区间内的值。
但是!!! 大多数现代计算机将实际的表示范围规定未-128~127
取模运算在计算时 商值-->向负无穷方向舍弃小数位
取余运算在计算时 商值-->向0方向舍弃小数位
例如:
-258➗256=1.0078125
-258对256取模:-258%256=-2(即商-1,余-2)
-258对256取余:-258/256=254(即商-2,余-254)
-1➗256=0.00390625
-1对256取模:-1%256=255(即商-1,余255)
-1对256取余:-1/256=-1(即商0,余-1)
unsigned u = 11;while(u > 0){cout << u << endl;}
mermaid
graph LR
A[算数类型] --> B[integaral type-整型/字符/布尔]
A --> C[浮点型]
E[空类型]
注:空类型(不对应任何值)------>函数不返回任何值(常见示例)
(前缀)字符、字符串字面值
L’a’ //宽字符型字面值(由两个字符表示?), wchar_t
u8"hi" //utf-8字符串字面值(utf-8用8位编码一个Unicode字符)
整型字面值(后缀)
42ULL //无符号整型字面值,类型是usigned long long
浮点型字面值(后缀)
1E-3F
3.14159L
long double ld = 3.1415926536;
int a{ld}, b = {ld} // 错误,转换未执行,因为错在丢失风险
int c(ld), d = ld; // 正确,转换执行,且确实丢失了部分值
//file_1.c定义并初始化了一个变量,该变量能被其他文件访问
extern const int bufSize = fuc();//file_1.h或者file_2.h头文件
extern const int bufSize; // extern作用:bufSize并未本文件所有,它的定义在别处出现
int i = 42;
const int &r1 = i;
const int &r2 = 43;
const int &r2 = r1 * 2;
#include <iostream>
using namespace std;int main()
{// example1double d = 3.1415926;const int &i1 = d; // 等效为 int temp = d; const int &i1 = temp;cout << "i1:" << i1 << endl;d = 20;cout << "i1:" << i1 << endl << endl;// example2int i = 3;const int &i2 = i * 2; // 等效为 int temp = i * 2; const int &i2 = temp;cout << "i2:" << i2 << endl;i = 10;cout << "i2:" << i2 << endl << endl;// example3i = 3;const int &i3 = i;cout << "i3:" << i3 << endl;i = 10;cout << "i3:" << i3 << endl;return 0;
}
输出如下
i1:3
i1:3i2:6
i2:6i3:3
i3:10
注:一般的,指针的类型必须与所指对象类型一致。例外情况:允许令一个指向常量的指针指向一个非常量对象;
double dval = 3.14;
const double *cptr; // 指针常量
cptr = &dval;
常量引用、指针常量,是引用或者指针‘自以为是’,觉得自己之指向了常量,所以不自觉不去改变所值的对象的值。
const double pi = 3.1415926;
const double *const pip = π // 指向常量的常量指针
注:此处指向常量和常量指针定义采用C++ Primmer,可能与流程说法不同。
// examlpe
const int ci =42; // 不能改变ci的值,这是一个顶层const
consdt int *p2 = π // 允许改变p2的值,这是一个底层const
const int *const p3 = p2; // 左边是底层const(指针所指对象是一个常量)// 右边是顶层const (指针对象是一个常量)
const int &r =ci; // 用于声明的的const都是底层const
注:
// example
int i =3;
const int *const p3 = &i;
int *p4 = p3;//错误,p3说:不行啊,我的女朋友要求比较高,你配不上
int *p5 = p3;//错误,p3说:不行啊,我的女朋友要求比较高,你配不上
const int p6 = p3; //正确,p3说:还是老六质量高啊(老六是个底层const)const int ci = 42;
int &r = ci; //错误,ci说:不行啊,你这顶帽子Low了
int &r2 = ci; //正确,ci说:我就是需要质量高的帽子
#include <iostream>
using namespace std;int main()
{constexpr int i = 42;constexpr const int *p = &i;return 0;
}
报错如下:
main.cpp: In function ‘int main()’:
main.cpp:7:27: error: ‘& i’ is not a constant expression7 | constexpr const int *p = &i;| ^~
正确应该修改为
#include <iostream>
using namespace std;constexpr int i = 42;
constexpr const int *p = &i;
int main()
{//constexpr int i = 42;//constexpr const int *p = &i;cout << "*p: " << *p << endl;return 0;
}
课后遗留疑问:那么constexpr一般只在函数外部使用是吗?
指针与constexpr
int j = 0;
constexpr int *p1 = &j; // p1是常量指针,指向整数j// 等效为int *const p1 = &j;
typedef double wages; // wages 是double同义词
typedef wages bae, *p // wages 是double同义词,p是double*同义词
typedef char *pstring;
const pstring cstr = 0; // cstr是指向char的常量指针
const pstring *ps; // ps是一个指针,他的对象是指向char的常量指针// 类似于const *const *ps;
注:
1)const 是对给定类型的修饰
2)使用类型别名声明后,pstring的基本类型是指针;
区别:使用char *重写后,基本数据类型是const char, *变成了声明符的一部分。
using SI = double;
typedef char (*p)(int); // 声明函数指针
p pFun; // 创建函数指针对象;
char glFun(int a){ return;}
void main()
{ pFun = glFun; // 初始化函数指针对象;(*pFun)(2);
}
int i = 0, &r = i;
auto a = r; // a是一个整数(r是i的别名,而i是一个整数)
const int ci = i, &cr = ci;
auto b = ci; // b是一个整数(ci的顶层const特性被忽略)
auto c = cr; // c是一个整数(cr是ci的别名,ci本身是一个顶层const)auto d = &i; // d是一个指向整型针(整数的地址就是**指向整数的指针**)
auto e = &ci; // e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
const auto f = ci; // ci的推演类型是int,f是const int
auto &g = ci; // g是一个整型常量的引用,绑定到ci
auto &h = 42; // 错误,不能将非常量引用绑定到字面值
const auto &j = 42; // 可以为常量引用绑定字面值
auto k = ci, &l = i; // k是整数(顶层const被忽略),l是整形引用
auto &m = ci, *p = &ci; // m是整型常量的引用,p是指向整型常量的指针
auto &n = i, *p2 = &ci; // 错误,i类型是int,而&ci类型是const int???
int i = 42, *p = &i, &r = i, j = 43;
decltype(r) b = &j; // b 是一种引用类型
decltype(r + 0) c; // c是一个(未初始化_的int,因为加法的结果是int
decltyp(*p) d; // 错误:c的类型是int &(引用),必须初始化
*p中*为解引用,解引用指针可以得到指针所指对象,还能给该对象赋值,故decltyp(*p)结果类型是int&,而非int。
struct Scales_data
{std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;
};// First choice to definite an object according with the class(not goog)
struct Scales_data{* ... *} accum,trans, *salesptr;
// Second choice to definite an object according with the class
struct Scales_data{* ... *};
Scale_data accum,trans, *salesptr;
注:最好将类定义和对象定义分开,所以第二种方式较好。
(1)#define 预处理命令可以避免重复包含(重复包含头文件,会触发重定义问题)。
(2)头文件一旦改变,相应的源文件必须重新编译以获得更新后的声明;
(3)预处理变量无视C++语言关于作用域的规则。
#include <iostream>
#include <string>
#include <sstream>using namespace std;int main()
{cout << "start cout in word!!!" << endl;string temp_a = "111 222 333 n 444, 555 777n 888 999 1111";string line = "";istringstream aa(temp_a);istringstream bb(temp_a);while(getline(aa, line)){cout << line << endl;}cout << endl<< endl;cout << "start cout in word!!!" << endl << endl;while(bb>>line){cout << line << endl; // doesn‘t cont backword}return 0;
}
输出如下
start cout in word!!!
111 222 333
444, 555 777
888 999 1111start cout in word!!!111
222
333
444,
555
777
888
999
111
其他人的回答
#include <iostream>
using namespace std;
int main()
{/*string word;while(cin>>word){cout << word << endl;}*/string line;while(getline(cin, line)){cout << line << endl;}return 0;
}
示例如下
#include <iostream>
#include <string>using namespace std;int main()
{string sa = "123456789";string sb = "1239";cout << "sa: " << sa << endl;cout << "sb: " << sb << endl;if(sa < sb){cout << "sa < sb" << endl;}else if(sa > sb){cout << "sa > sb" << endl;}else{cout << "sa = sb" << endl;}size_t position_start = sa.find("34");if(position_start != string::npos){cout << position_start << endl;string ssa = sa.substr(position_start,sizeof("78")/sizeof(char));cout << "ssa: " << ssa << endl;}return 0;
}
注意:vector是一个类模板,若初始化为空vector,不能使用vector[i]进行赋值, vector只能对确定已知的元素执行下标操作
疑问: 1.如何删除vector中的元素
疑问: 2.如何插入vector中的元素
ivector.insert(ivector.begin()+2,11111);
注:迭代器在被插入或者删除元素后,迭代器都会失效
so: 使用了迭代器的循环体,都不要像迭代器所属容器添加元素(来源:C++ Primmer第5版P99)
#include <iostream>
#include <vector>
#include <string>
using namespace std;int main()
{vector<int> ivector;vector<int>::iterator iter;ivector.push_back(0);ivector.push_back(10);ivector.push_back(20);ivector.push_back(30);ivector.push_back(40);cout << "the oral vector is :" << endl; for(iter=ivector.begin();iter&d();iter++){cout << " " << *iter;}ivector.insert(ivector.begin()+2,11111);cout << endl << "after insert 1111 in the fourth position, the vector is :" << endl; for(iter=ivector.begin();iter&d();iter++){cout << " " << *iter;}ase(ivector.begin()+1);cout << endl << "after delete the first order position, the vector is :" << endl; for(iter=ivector.begin();iter&d();iter++){cout << " " << *iter;}ase(ivector.begin()+1, ivector.begin()+3);cout << endl << "after delete the first order and the second position, the vector is :" << endl; for(iter=ivector.begin();iter&d();iter++){cout << " " << *iter;}return 0;
}
疑问: 3.迭代器可以知道自己在容器中的位置吗?
可以通过distance(vector.begin(),iteror)实现, 示例如下:
#include <iostream>
#include <vector>
using namespace std;int main () {vector<int> mylist;for (int i=0; i<10; i++) {mylist.push_back (i*10);}vector<int>::iterator first = mylist.begin();vector<int>::iterator last = d();vector<int>::iterator it = first;for(;it != last;++it){cout<<"第"<<distance(first,it)<<"个元素的值为:"<<*it<<endl;}return 0;
}
#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> ivector;cout << "ivector's size is: " << ivector.size() << endl;int itemp;while(cin >> itemp){ivector.push_back(itemp);}vector<int>::iterator iterbegin = ivector.begin(), iterend = d();if(iterbegin == iterend){cout << "this is a empty vector" << endl;return -1;}iterend -= 1;int order = 1;while(iterbegin <= iterend){if(iterbegin == iterend){cout << "the last result of addition: " << *iterbegin << endl;}else{cout << "the " << order << " result of addition: " << (*iterbegin + *iterend) << endl;}order += 1;iterbegin += 1;iterend -= 1;}cout << "Hello World";return 0;
}
-使用for(新特性?)循环处理多维数组,除了最内层循环外,其他所有循环控制变量都应该使用引用类型
否则如下如果初始化row时,row是指向数组首元素的指针,类型是int *,内层循环不合法(我试了下,内部解引用好像也会报错)。
#include <iostream>
#include <vector>
using namespace std;int main()
{vector<string> svector;string temp;while(cin >> temp){svector.push_back(temp);}for(auto &s:svector){for(auto &c:s){c = toupper(c);}}for(auto s: svector){cout << s << endl;}return 0;
}
#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> a(10, 42);vector<int> b{42, 42,42, 42, 42, 42, 42, 42, 42, 42};cout << "vector a' elements: ";for(auto &i: a){cout << i << ", ";}cout << endl;cout << "vector b' elements: ";for(auto &i: b){cout << i << ", ";}cout << endl;vector<int> c;for(int i =0 ; i <10; i++){c.push_back(42);}cout << "vector c' elements: ";for(auto &i: c){cout << i << ", ";}cout << endl;return 0;
}
读入一组整数并把它们存入一个vector,每对相邻整数的和输出出来;改写你的程序,这次要求先输出第一个和最后一个的和,接着输出第2个和倒数第2个数元素的和,以此类推。
PS:感觉两问差不多,我只做了第二问。
#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> a;int temp;while(cin >> temp){a.push_back(temp);}vector<int>::size_type m_size = a.size();if(!(m_size%2)){for(int i = 0; i <= (m_size-2); i+=2){cout << (i/2+1) << ":" << a[i] + a[i+1] << endl;}}else{for(int i = 0; i <= (m_size-3); i+=2){cout << (i/2+1) << ":" << a[i] + a[i+1] << endl;}cout << (m_size/2 +1) << ": " << a[m_size-1] << endl;}return 0;
}
#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> ivector;int itemp;while(cin >> itemp){ivector.push_back(itemp);}auto first_iter = ivector.cbegin(), last_iter = d();if(first_iter == last_iter){cout << " input is empty, please check again." << endl;return 0;}--last_iter;int counter_couple = 0;while(first_iter < last_iter){cout << "the " << ++counter_couple << " couple: " << (*first_iter + *last_iter) << endl;++first_iter;--last_iter;}if(first_iter == last_iter){cout << "the " << ++counter_couple << " couple: " << *first_iter << endl;}return 0;
}
#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> ivector(11);int itemp;auto first_iter = ivector.begin();cout << "the socres is: ";while(cin >> itemp){cout << itemp << " ";(*(first_iter + itemp / 10))++;}cout << endl;for(int i = 0;first_iter != d() - 1; first_iter++){cout << "The number between the " << i * 10 << "~" << i * 10 +9 << " in socres has: " << *first_iter << endl;i++;}cout << "The number get 100 in socres has: " << *(d() - 1) << endl;return 0;
}
const关键字修饰数组:要求定义时就要赋予初值,且之后数组内元素不可改变。
以下定义非法:无符号数buf_size不是常量;
unsigned buf_size = 1024;
int ia[buf_size];
数组维度定义有两个要求:
1.大于0
2.常量表达式
全局变量和局部变量的区别、内置类型与复合类型的区别。
** String **:接受无参数的初始化方式。
所以无论数组在函数内还是函数外,都被默认初始化为空字符串。
** int(内置类型) **:
函数外:所有元素初始化为0;
函数内:不被初始化,程序试图拷贝或输出未初始化的变量,将遇到未定义的奇异值。
#include <iostream>
#include <string>
using namespace std;string sa[10];
int ia[10];
int main()
{string sa2[10];int ia2[10];cout << "sa: ";for(auto temp:sa)cout << temp << " ";cout << endl;cout << "ia: ";for(auto temp:ia)cout << temp << " ";cout << endl;cout << "sa2: ";for(auto temp:sa2)cout << temp << " ";cout << endl;cout << "ia2: ";for(auto temp:ia2)cout << temp << " ";cout << endl;return 0;
}
输出如下
sa:
ia: 0 0 0 0 0 0 0 0 0 0
sa2:
ia2: 1268149248 32637 1268101768 32637 1268144288 32637 1268096928 32637 6 0
1.数组定长:数组一旦定义,维度就是确定的。丧失了一些灵活性,但是软件运行效率在一定程度上得到增强。
2.数组没有size()成员函数
所以如果想获取长度,只能通过以下方式获取。
String数组:strlen函数
#include <iostream>
#include <cstring>
using namespace std;int main()
{char a[10] = {'1', '1', '1', '1', '1', '1', '1', '1', '1', '1'};cout << strlen(a) << endl;
}
输出是13,为什么那?
其他数组:sizeof(aray_name)/sizeof(aray_name[0])
#include <iostream>
#include <cstring>
using namespace std;int main()
{int a[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};cout << sizeof(a) / sizeof(a[0] ) << endl;
}
#include <iostream>
#include <vector>
using namespace std;int main()
{int a[] = {0, 1, 2, 3, 4, 5};int b[5];for(int i = 0; i < 5; i++){b[i] = a[i];}for(int i = 0; i < 5; i++){cout << "b[" << i << "]: " << b[i] << endl;}vector<int> va = {0, 1, 2, 3, 4, 5};cout << "vector_a:";for(auto i: va){cout << i << " ";}vector<int> vb(va);cout << endl << "vector_b:";for(auto i: vb){cout << i << " ";}return 0;
}
P105:在大多数表达式中,使用数组类型的对象其实是
使用一个指向该数组首元素的指针
PS1:就3.28练习题拓展说一下,有两种情况例外
PS2:指针占用几个地址?参考解释如下
32位系统是4个字节;64位系统就是8个字节
CPU和硬件直接通讯,只能通过内存与数据交互;
CPU通过地址总线、控制总线、数据总线与内存进行数据交互和操作
地址总线:代表寻址能力,比如32位系统就是32条地址线(0或者1)
控制总线:控制能力或者控制方式,比如读或者写
数据总线:数据传输速度,即单次数据传输量
参考习题册答案:
作用:使p1由原来所指地址指向p2所指向的位置。
同一数组,或者数据类型相同的不同数组都是合法的;
数据类型不同的不同数组是非法的。
PS:vector支持’!=',比较简单就不写了。数组array需要逐位比较,程序如下
#include <iostream>
using namespace std;int main()
{int a[] = {1, 2, 3, 4};int b[] = {1, 2, 5, 6};// don't use &a[0],because &a[0] is a address and occupy 8 bytes in 64 bit computer.int size_a = sizeof(a)/sizeof(a[0]); int size_b = sizeof(b)/sizeof(b[0]);cout << "sizeof(&a[0]):" << sizeof(&a[0]) << endl;cout << "sizeof(a):" << sizeof(a) << endl;cout << "sizeof(a[0]):" << sizeof(a[0]) << endl;cout << "the array a's size is:" << size_a << endl;if(size_a != size_b){cout << "a's sieze:" << size_a << ", size_b:" << size_b << "different!" << endl;}else{for(int i = 0; i < size_a; i++){if(a[i] != b[i]){cout << "in the " << i << " postion, they are different! a'member:" << a[i] << ", b'member:" << b[i] << endl;break;}else{cout << "in the " << i << " postion, a'member:" << a[i] << ", b'member:" << b[i] << endl;}}}cout << "Hello World";return 0;
}
C标准库string函数(cstring)
大小 | 返回值 |
---|---|
p1>p2 | >0 |
p1==p2 | =0 |
p1<p2 | <0 |
#include <iostream>
#include <cstring>using namespace std;int main()
{// remember: 'strcmp'and strcpy must compare or copy some objects end with '