1.在C++中char有无符号是不确定的,默认类型由编译器决定,需要你显示的说明unsigned or signed。以前本科毕设将contiki移植到cc2530上时,就遇到过这个问题导致的死循环
2.对于浮点用double,有10位有效数字(float常常精度不够但开销差不多),long double一般是没有必要的
3.给无符号类型赋超过他的范围的值,结果为取模后的结果,给带符号类型赋超过他范围的值的结果是未定义的
//结果为255
unsigned char c1=-1;
//结果为未定义
signed char c2=256
4.当一个算术表达式中既有无符号数又有int值时,此int值会自动转化为无符号类型;从无符号数中减去一个值,需要确保结果不能是一个负值(如果是个负值会自动取模,类似1)
5.注意八进制是0开头,如024表示八进制(oct),0x24表示16进制(hex),24表示十进制(dec);另外小数若用科学技术法记,则指数部分可以用 E or e 来表示(0. 0e0 .001都是可以的)
6.泛化的转义字符:使用\x后面紧跟1个或多个十六进制数字(最多不超过四个,超过的按单独的其他字符计算),使用\后面紧跟1个,2个,3个八进制字符(同样的,超过的按其他单独字符来看)
7.初始化问题:c++11中可以了花括号形式的列表初始化,而且这形式不允许可能丢失数据的类型转换
另外:对于定义在函数体内的内置类型对象若未初始化,其值是未定义的;对于类的对象没有显示初始化,其值由类确定
long double ld=3.1315926536
int a{ld},b={ld}; //错误:转换未执行,因为可能存在丢失信息的风险
int c(ld),d=ld; //正确:转换执行,且确实丢失了部分值。小括号是没有等号的形式的
8.任何包含了显示初始化的声明,即成为了定义
extern int i; //声明i而非定义i
extern double pi=3.1416; //定义
9.当作用域符左侧没有域名称时,向全局作用域发出请求,请求符号右侧的名称(全局作用域没有名字;若有同名的局部变量,仍只用全局的)
10.指针和引用最大的区别:引用不是一个对象(不能有引用的引用之类的),一单定义了引用,就无法再绑定到其他对象上去了;而指针本身是一个对象,没有这些限制(对于空指针,nullptr为0,NULL亦为0,后者需要包含cstdlib)
//i为int型的数,p为指针,r为引用
int i=1024,*p=&i,&r=i;
//b是一个整形指针的引用(从右往左阅读,看到&b知道b是引用,看到*说明指向一个指针)
int *a;
int *&b=a;
int c=10;
b=&c;
11.如果想在多个文件之间共享const对象,需要在变量定义之前添加extern,注意是在定义处添加,其他文件中要引用是使用extern声明即可。(对于常量,const是在编译期间替换值的,宏定义在预编译期间替换值)
12.常量、字面值的引用都必须是常量(即常量引用),需要用const修饰;指针也是如此,但是不能指向字面值,表达式(即指针的类型必须与被指向的对象类型一致,但是常量指针可以指向变量)
int i=42;
const int &r1=i; //正确,常量引用
const int &r2=42; //正确,字面值的常量引用
const int &r3=i*2; //正确
int &r4=r1*2; //错误
13.
顶层const:指针本身是个常量(我们俗称指针常量,但是在C++ Primer中指针本身为常量的称作为常量指针)
底层const:指针所指向的对象是一个常量(常量指针)
//其实把int *看做一个整体的类型声明,若const在后面表顶层,若在前面表底层(从右往左看,先顶再底)
int i=0;
int *const p1=&i; //顶层const,从右往左看首先是个const表示是常量,其次*为声明表示类型为指针
const int ci=42;
const int *p2=&ci; //底层const,从右往左看首先是个指针
const int *const p3=p2;//靠右的为顶层const,靠左的为底层const
const int &r=ci; //声明引用的const都是底层const,他自己本身就没法改变(但是若果常量引用指向非常量,被指向的可能能改变)
14.常量表达式,在编译期间就能到得到计算结果的表达式
const int a=1; //a是常量表达式
const int b=a+1; //b是常量表达式
int c=12; //普通变量,初始化值为字面值常量罢了
const int sz=get_size(); //需要运行时才能够确定值,不是常量表达式
//在c++ 11中可以用constexpr声明变量,以便由编译器验证实收变量的值为常量表达式
constexpr int mf=20; //20是常量表达式
constexpr int limit=mf+1; //mf+1是常量表达式
constexpr int sz=size(); //当size()是一个constexpr函数时,这条语句才正确
constexpr和指针作用时:始终声明的是顶层指针(指针自己的值即存放的地址不能改变)
const int *p=nullptr; //p是一个指向整形常量的指针
constexpr int *q=nullprt; //q是一个指向整数的常量指针
15.类型别名:两种方法
//1、使用typedef
typedef double wages; //wages是double的同义词
typeder wages base,*p; //base是double的同义词,p是double *的同义词
//2、使用using
using SI = Sales_item;
易错点:不要把原定义直接带入
typedef char *pstring;
const pstring cstr=0;//cstr本身是一个常量,而且他又是一个字符指针,即指针常量(书中称为常量指针)
//如果直接带入定义,那么就会得到错误的结果
const char *cstr=0; //cstr是一个指向const char的指针,是个顶层const
16.auto和decltype的区别
auto:编译器会推测变量类型,一般会忽略掉顶层const(修饰自己的,从右往左第一个),底层const会保留些来
//一个auto只能声明一个类型
auto i=0,*p=*i; //正确:i为int,p为int *
auto sz=0,pi=3.14; //错误:sz和pi类型不一致
//顶层const会被忽略掉
const int ci=i,&cr=ci;
auto b=ci; //b为int类型,ci的顶层const被忽略掉了
auto c=cr; //c为int类型,cr为ci的别名,而ci又是顶层const
auto d=&i; //d为int *类型
auto e=&ci; //e为常量指针
decltype:其内部表达式是什么类型,就返回什么类型;注意指针解引用返回的类型的引用!!!对于decltype内用双层括号的返回的永远是引用类型
//1.decltype使用
const int ci=0,&cj=ci;
decltype(ci) x=0; //x是const int 类型
decltype(cj) y=x; //y是const int &类型,y绑定到x上
decltype(cj) z; //错误:z是一个引用,必须初始化
//2.decltype与引用
int i=42,*p=&i,&r=i;
decltype(r+0) b; //正确:b为未初始化的int类型
decltype(*p) c; //错误:解引用后得到所指的对象,能够给这个对象赋值,因此c是int &类型,而非int
//3.双层括号返回的永远是引用
decltype((i)) d; //错误:d是int &,必须初始化
decltype(i) e; //正确:e是一个未初始化的int
17.对类内初始值需要使用等号或者花括号赋值,不能使用圆括号