目录
参考:《深入理解Android:JAVA 虚拟机ART》
C++基础数据类型
包括:int,short,long,long long,bool,char,float和double
由于C++和硬件平台关联较大,规范没办法像Java那样严格规定每种数据类型所需的字节数,所以它只定义了每种数据类型最少需要多少字节。
C++定义了sizeof操作符,通过这个操作符可以得到每种数据类型(或某个变量)占据的字节个数
//整型,sizeof(int):至少2个字节
int i = 0,j={1},k{123}; //三种赋值方式
cout << "整型,长度=" << sizeof(int) << endl;
cout << "i= " << i << " j= " << j << " k= " << k << endl;
//短整型,sizeof(short)至少2个字节
short ashort = 0xab;
cout << "短整型,长度=" << sizeof(short) << " " << ashort << endl;
//长整型,sizeof(long):至少4个字节
long along = 1234;
cout << "长整型,长度=" << sizeof(long) << " " << along << endl;
//长整型,sizeof(long long):至少8个字节
long long alonglong = 0xffffffff00000000;
cout << "长整型,长度=" << sizeof(long long) << " " << alonglong << endl;
//布尔型,sizeof(bool):规范未定义
bool abool = false; //true
cout << "布尔型,长度=" << sizeof(bool) << " " << abool << endl;
//字符型,sizeof(char):至少1个字节
char achar = 'x';
cout << "字符型,长度=" << sizeof(char) << " " << achar << endl;
//单精度浮点。对于浮点数,规范只定义了浮点数最少支持多少个有效数字
float afloat = 1.2345678910;
cout << "单精度浮点,长度=" << sizeof(float) << " " << afloat << endl;
//双精度浮点。规范定义float是6个有效数字,double至少有10个有效数字
double adouble = 1.23456789;
cout<<std::setprecision(10)<<"双精度浮点,长度=" <<
sizeof(double) << " "<<adouble << endl;
C++中除bool和浮点数之外,其他基本数据类型还可细分为符号和有符号两种
//无符号类型由unsigned xxx来修饰,比如:
unsigned int aunint = 0xffffffff;
unsigned short aunshort = 0x1fff;
unsigned char aunchar = 0xff;
指针
//指针,由"类型 *" 定义。
int *pint = &i; //&i表示取某个变量的地址,由&取地址符号表达
int &aliasOfJ = j; //引用,由"类型 &"定义
cout<<"i的内存地址为"<<pint<<" 内存地址存储的内容为:" << (*pint)<<endl;
cout<<"j= "<<j<<" anotherInt= "<<aliasOfJ<<endl;
/*void:空类型,注意:
(1)void作为类型,只能修饰指针,比如此处的void*
(2)C++11中,空指针由nullptr表示,取代了以前常用的NULL
*/
void* px = nullptr;
cout<<"px的值为"<<px<<endl;
指针本质上代表了虚拟内存的地址。简单点说,指针就是内存地址。比如,在32位系统上,一个进程的虚拟地址空间为4G,虚拟内存地址从0x0到0xFFFFFFFF,这个段中的任何一个值都是内存地址。
指针类型
int *p,变量p是一个指针,它指向的内存存储了一个(对于数组而言,就是一组)int型数据
short *p,变量p指向的内存存储了一个(或一组)short型数据
int (*p)(int argc,char* argv[]),变量p指向一个返回值为int 参数为int 和char*的函数入口地址
int mymain(int argc,char*argv[]){
//pmain是一个函数指针变量。注意它的格式,它和目标函数(mymain)的参数和返回值类型
//完全匹配
int (*pmain)(int argc,char* argv[]);
pmain = mymain;//pmain指向了mymain函数
pmain = &mymain;//取mymain函数的地址给pmain变量,效果和上面一种方法一样
pmain(0,nullptr);//调用pmain函数,其实就是调用mymain函数
}
指针赋值
//指针型变量的赋值
int* px = (int*)0x123456;//给px任意设置一个值
int* py = new int;//从堆上分配一块内存,内存地址存储在py中
long z = 100;
long* pz = &z;//通过取地址符号&,将z的地址赋值给pz
//函数指针变量的赋值
int (*pmain)(int argc,char* argv[]);
pmain = mymain;//效果和下条语句一样,将mymain函数地址赋值给pmain变量
pmain = &mymain;
指针的解引用
指针只是代表内存的某个地址,通过 解指针引用符号* 获取该地址对应内存中的内容
//指针解引用,获取对应内存地址中的值
(*py)=1000;
long zz = (*py) + 123;
//函数指针解引用,意味着要调用对应的函数
pmain(100,nullptr);
(*pmain)( 100,nullptr);
引用
引用只是变量的别名。由于是别名,所以C++要求在定义引用型变量时就必须将它和实际变量绑定。·引用型变量绑定实际变量之后,这两个变量(原变量和它的引用变量)其实就代表同一个东西了。代码注释中以鲁迅为例,“鲁迅”和“周树人”都是同一个人。
void testPointersAndReference(){
/*下面4条语句为指针的操作
(1)px开始指向x的地址,
(2)然后我们使它指向y的地址指针的取值很随意,可以任意赋地址值,只要类型匹配。
*/
int x = 12345;
int *px = &x; //px指针指向x的地址
int y = 2222;
px = &y; //修改px指针,使它指向y的地址
/*下面是引用操作,引用和指针有很大不同:
(1)引用在定义的时候就必须和某个变量绑定。通俗点说,引用是一个变量的别名。
(2)如果定义时不绑定某个变量,编译报错。
(3)绑定后,引用和原变量实际是一个东西。就好像鲁迅其实是周树人的笔名一样,周树人是鲁迅,鲁迅就是周树人。鲁迅身上发生的任何事情,就是周树人身上发生的事情
*/
int &aliasX = x;//定义引用aliasX,这个引用和x关联.
//设置aliasX的值为54321.那么,x的值也变成54321.
//x就是aliasX,aliasX就是x.
aliasX = 54321;
changeRef(aliasX);//该函数返回后,x值变成9999
//int &aliasY; //编译错误,引用定义时必须和一个变量绑定
}
/*引用的作用之一体现在函数调用上。函数形参如果定义为引用,则函数内部修改了形参的值,实参也会相应发生修改。比如下面代码中的三个函数的区别:
(1)changeRef:由于alias为引用,不是指针,所以可直接操作alias
(2)changeNoRef:x不是引用。函数内部修改其值为9999,函数返回后不影响实参
(3)changePointers:通过指针来修改实参的值为9999,但是每次操作指针类型的数据都得用*号。不如1方便
*/
void changeRef(int & alias){
//修改形参的值为9999,该函数返回后,实参的值就变成了9999
alias = 9999;
}
void changeNoRef(int x){
//修改形参的值为9999,但该函数返回后,实参并不受任何影响
x = 9999;
}
void changePointers(int* pInt){
//也能通过修改形参的值来修改实参的值为9999,但是,操作形参时,必须使用解指针引用符号*
*pInt = 9999;
}
字符和字符串
char iamchar = 'c';//字符常量
cout<<"iamchar="<<iamchar<<endl;
iamchar = 0x12; //字符常量
cout<<"iamchar="<<iamchar<<endl;
/*下面是字符串常量,中间的\n为换行符。输出结果为:
hello
world
*/
const char* strings = "hello\n world";
cout <<strings<<endl;
/*下面这两个strings的输出都是:hello \n world
字符串中的”\n”等属于特殊符号,如果就是要输出"\n"这两个字符的话,有两种方法:
(1)通过转义字符\来处理,比如”\\n”。这样的话,C++就不会将\n当作特殊符号处理
(2)通过R"()"定义所谓的Raw string(原始字符串),字符串里边的内容都不会被转义
*/
strings = "hello \\n world";
cout <<strings<<endl;
strings = R"**123(hello \n world")")**123";
cout <<strings<<endl;
数组
//定义数组,数组的长度由初值个数决定
int intarray[] = {1,2,3,4,5};
cout<<"array size = " << sizeof(intarray)/sizeof(intarray[0]) <<endl;
//指定数组长度.由于shortarray是在栈上分配的数组,其长度
//必须在编译期就确定.所以,代表数组长度的size必须是常量
const int size = 10;
short shortarray[size];
//动态数组,其长度可以在运行时决定
int dynamic_size = 4;
int *pintArray = new int[dynamic_size]/*{10}*/;
/*下面的for循环中,pintArray是一个int型的指针,它指向一块内存。不过,这块内存只包含一个int型数据还是包含一组int型数据?这个问题的答案只有开发者自己才知道。另外,pintArray+i指向数组第i个元素的地址,然后通过*解引用得到元素i的内容*/
for(int i = 0; i < dynamic_size; i++){
cout<<pintArray[i]<<endl;
cout<<*(pintArray+i)<<endl; //c和c++中,指针和数组有着天然的联系
}