您的位置:首页 > 编程语言 > C语言/C++

C++变量和基本类型

2016-05-14 20:44 218 查看
C++变量和基本类型

数据类型是程序的基础:它告诉我们数据的意义以及我们能在数据上执行的操作。

基本内置类型

当我们赋给无符号类型一个超出它表示范围的值是,结果是初始值对无符号类型表示数值总数取模后的余数。
表达式里既有无符号类型也有无符号类型,则会有符号类型会自动转换成无符号类型再运算。

变量

基本形式:类型修饰符+变量名,定义:基本数据类型+类型修饰符()可为空+变量名。

对象是指一块能存储数据并具有某种类型的内存空间。
初始化是创建变量时候赋予其一个初始值,而赋值是把对象的当前值擦除,再以一个新值来替代。
C++11新标准允许列表初始化,用花括号来初始化变量,但是用于内置类型时会有警告产生。
定义与任何函数体外的全局变量默认初始化为0,函数体内的变量的默认初始化值是未定的。

声明使得名字为程序所知,而定义负责创建与名字关联的实体。变量声明规定了变量的类型和名字定义除此之外还申请内存空间,也可能为变量赋一个初始值。声明:external int i; 声明+定义:int j; 任何包含显示初始化的声明即成为定义,如extern double pi=3.14;此句为定义。
不论在程序和什么位置,使用到的名字都会指向一个特定的实体:变量、函数、类型等。同一个名字如果出现在不同的位置,也可能指向不同的实体。C++中大多数以花括号分隔作用域。名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。因为全局作用域本身没有名字,所以作用域操作符的左侧为空时,向全局作用域发出请求获取作用域操作符右侧名字对应的变量。

复合类型——引用和指针

一条声明语句由一个基本数据类型和紧随其后的一个声明符列表组成。每个声明符命名一个变量并指定该变量为与基本数据类型有关的某种类型。声明符有两类:第一类是简单声明符就是变量名;第二类是复杂声明符,它基于基本数据类型得到更复杂的类型,并把它指定给变量。引用分为“左值引用”和“右值引用”,后者为C++11新增,引用通常指左值引用。引用和指针都实现了对其他对象的间接访问。

引用:给对象起一个别名,通常声明符为&d的形式。引用不是对象,不占据内存空间,它只是为一个已存在的对象起另一个名字。引用必须被初始化,将引用和初始值绑定,此后无法令引用绑定到另外一个对象。在引用上所进行的操作都是在与之绑定的对象上进行的。因为引用本身不是对象,所以不能进行引用的引用,即非对象不能进行引用,引用只能绑定在对象上,而不能是字面值或某个表达式的计算结果。

指针:指针本身就是对象,可以先后指向不同的对象,无须再定义时候赋初值。指针中存放所指向对象的地址,如:int *p=&d;指针p指向int 型数据d,指针p中存放变量d所在内存中的地址。解引用指针p可以得到其所指向的对象,如*p=9;std::cout<<*p<<std::endl;为指针p所指向的对象即d赋值9,相当于d=9,然后输出d变量的值。

指针有四种状态:指向一个对象;指向紧邻对象所占空间的下一个位置;空指针;无效指针;
空指针不指向任何对象:int *p=nullptr 或者 int *p=0 或者 int *p=NULL但是这个需要#include<cstdlib>
void* 指针是一种特殊的指针类型,可以存放任意类型对象的地址。不能直接操作void 指针所指向的对象,因为不知道该对象是什么类型。

符号的多重含义:

int i=42;
int &r=i; //&紧随类型名出现,因此是声明的一部分,表示r是一个引用。
int *p; //*紧随类型名出现,因此是声明的一部分,表示p是一个指针。
p=&i; //&出现在表达式中,是一个取地址符。
*p=i; //*出现在表达式中,是一个解引用符。
int &r2=*p; //&是声明的一部分,*是一个解引用符

复合类型的声明:

int i=1024, *p=&i, &r=i; //i是一个int型数,p是一个int 型指针,r是一个int型引用。
变量的定义包括一个基本数据类型和一组声明符。同一条语句中基本数据类型只有一个(如上的int),但是声明符的形式却可以不同。声明符包括类型修饰符(如上的*和&)和变量名。
指向指针的指针:int i=1024; int *p=&i; int **pp=&p; //p指向一个int型的数,pp指向一个int型的指针。
指向指针的引用:int i=1024; int *p; int *&r=p; //p是一个int型指针,r是一个对指针p的引用,*&第一个类型修饰符*代表等式右边指针p的类型修饰符,第二个类型修饰符&声明变量r本身是引用。判断一个变量名的类型,从左侧最靠近变量名的类型修饰符看,r的左侧第一个类型修饰符是&说明r是一个引用,继续往左看得到int
*,说明r引用的是int型指针。
由于引用本身不是对象,所以没有指向引用的指针和指向引用的引用。

const 限定符

希望某一个变量的值不被改变。因为const对象一旦创建后其值不变,因此const对象必须被初始化。只能在const型的对象上执行不改变其内容的操作。const的常量特征仅仅在执行改变该该对象的操作时才会发挥作用。
默认情况下const对象仅在本文件内有效,当多个文件出现同名的const变量时,其实等同于在不同文件分别定义了独立的变量。如果想要在一个文件中定义const,而在其他多个文件中声明并使用它,就需要如下方法:external const int bufSize=fuction(); //在file1.c文件中定义并初始化,用external加以限定使其被其他文件使用。
extern const int bufSize;//在file2.h头文件中声明,并用extern做限定,指明bufSize并非本文件所独有,它的定义出现在别处。如果想要在多个文件之间共享const 对象,必须在变量定义之前添加external关键字。
指向常量的指针或引用,只是指针或引用本身是常量,即不能通过指针或引用来改变指向对象和引用对象的值,但是该对象是否为常量都是可以的.

引用和const:对const 的引用(常量引用):对常量的引用也必须用常量且不能通过该常量的引用修改所引用对象的值。

const int c=1024; const int &r1=c;//正确的对常量的引用。
r1=128;//错误,r1是对常量的引用,不能修改。 int &r2=c;//错误,试图让一个非常量引用指向一个常量对象。、
初始化常量引用可以用任意表达式作为初始值,只要该表达式结果能转换成引用的类型即可。 内部原理如下:

double val=3.14; const int &r=val;//此处r引用一个int 型数,但val却是一个浮点型数而非整数。为了确保让r绑定一个整数,编译器把代码变成如下:const int temp=3.14;//有双精度浮点数生成一个临时的整形常量 const int &r=temp;//让r绑定这个临时量。
对const的引用可能引用一个非const对象或者一个const对象。

指针和const:常量指针(指向常量的指针)

和常量引用一样,指向常量的指针的引用也可能引用 非常量或者常量。所谓指向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象是否为常量。所以更为确切的叫法应该是常量指针(说明指针性质是常量)而不是指向常量的指针(说明指针对象是常量)。
常量指针必须初始化。把*放在const关键词之前说明指针是一个常量,而指针指向的对象不是,即不变的是指针本身而不是指向的那个对象。如: int *const p=&n;//指针p只能指向对象n,但是对象n的值可以被修改。
cosnt double pi=3.14; const double *const pip=π//pip是一个指向常量对象的常量指针。

顶层const:指针本身是一个对象,因此指针本身是不是常量和指针所指向对象是不是常量是两个问题。

顶层const:指针本身是个常量。
底层const:指针指向的 对象是个常量。
const int p1=22; const int *const p=p1;//靠右的const是顶层const,说明指针p本身是常量;靠左的是底层const,说明指针p指向的对象是常量。

constexpr和常量表达式

由数据类型和初始值(字面值常量或者const 常量)组成。
一个constexpr指针的初始值必须是nullptr或者0,或者存储于某个固定地址中的对象。

处理类型

程序复杂性体现在:一些类型难以“拼写”;搞不清到底需要哪些类型。

类型别名:typedef :typedef double wages;//wages是double的同义词。
C++11新标准添加“别名声明”。 using SI=Sales_item;//SI是Sales_item的同义词。
指针、常量和类型别名:typedef char *ps; const ps cstr=0;//cstr是指向char的常量指针。 const ps *psp;//psp是一个指针,它的对象是指向char的常量指针。
auto类型说明符,用它让编译器替我们去分析表达式所属的类型。auto定义的变量必须有初始值。 auto item=vall1+vall2;
auto &h=22;//错误,不能为非常量引用绑定字面值。该位const auto &h=22;
decltype类型指数符:从表达式的类型推断出要定义的变量的类型,但是不用表达式的值初始化该变量。选择并返回操作数的数据类型。
decltype与引用:如果decltype使用的表达式不是一个变量,则返回表达式结果对应的类型。如果是解引用操作,则返回引用类型。 //decltype的结果可以是引用类型。
int i=22,*p=&i, &r= i; decltype(r+0) b;//正确,加法结果是int,因此b是一个未初始化的int.
decltype(*p) c;//错误,decltype返回类型是int &,必须被初始化。
如果decltype使用的是一个不加括号的变量,则得到的结果是该变量的类型;如果加上一层或多层括号,编译器就会把它当作是一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的decltype就会得到引用类型。
decltype((i)) d;//错误,d是int&,必须被初始化 decltype(i) e;//正确,e是一个未初始化的int

自定义数据结构

类体右侧的表示结束的花括号后必须写一个分号,这是因为类体后面可以紧跟变量名以示对该类型的定义,所以分号必不可少:struct Sales_data{/**/} a,b,*c;
类内某认初始值为空或为0,类内初始值或者放置花括号里,或者放在等会右边,记住不能使用圆括号。

小结:类型分为非常量和常量,一个常量对象必须初始化,而且一旦初始化其值就不能再改变。全局作用域的内置类型对象初始化为0;局部作用域的对象未被初始化即拥有未定义的值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: