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

c++ primer 第2章 变量和基本类型

2017-04-15 21:33 183 查看
2.变量和基本类型

2.1基本内置类型

2.1.1算数类型

算数类型:

整形(字符型,布尔型)

浮点型

算数类型尺寸:

该数据类型所占的比特数

类型 含义 最小尺寸 值

bool 布尔类型 未定义 真(true)或(false)

char 字符 8位

wchar_t 宽字符 16位

char16_t Unicode字符 16位

char32_t Unicode字符 32位

short 短整型 16位

int 整型 16位

long 长整型 32位

long long 长整型 64位

float 单精度浮点数 6位有效数字

double 双精度浮点数 10位有效数字

long double 扩展精度浮点数 10位有效数字

char大小 = 机器字节大小

long long>=long>=int>=short

带符号类型和无符号类型

unsigned int = unsigned

char:有可能表现为signed char,也有可能表示unsigned char,视编译器不同而不同

signed char

unsigned char

如何选择数据类型:

*明确数据不为负数,用unsigned数据类型

*int执行整数运算

*double执行浮点数运算

选型示例

银行利率,本金,付款的数据类型选择,都是double型

原因:利率本金付款都可能是整数或者实数,因此应该是浮点数运算,据上面总结用double类型最合适

2.1.2类型转换

bool          b = 42;  //b为真
int           i = b;   //i的值为1
i = 3.14;              //i的值为3
double        pi = i;  //pi的值为3.0
unsigned char c = -1;  //假设char占8比特,c的值为255
signed char   c2 = 256;//假设char占8比特,c2的值是未定义的


*非bool—>bool

0 —>false

非0—>true

*bool—>非bool

false—>0

true —>1

*浮点数—>整型

保留浮点数中小数点之前的部分

*整型—>浮点数

小数部分记为0,如果该整数所占空间超过浮点类型的容量,精度可 能有损失

*用无符号类型表示超过其范围的数

此数对无符号类型表示数值总数取模后的余数

*用带符号类型表示超过其范围的数

结果是未定义

*不要混用unsigned和signed在一个表达式中

2.1.3字面值常量

八进制:0开头的整数,\XXX(后面3位才是8进制)

十进制:

十六进制:0x或者0X开头的整数,\x

字符常量:’a’

字符串字面常量:”hello world”(最后还有‘\0’)

字符和字符串字面值


前缀 含义 类型

u Unicode16字符 char16_t

U Unicode32字符 char32_t

L 宽字符 wchar_t

u8 UTF-8(仅用于字符串字面常量) char

整型字面值


后缀 最小匹配类型

u/U unsigned

l/L long

ll/LL long long

浮点型字面值


后缀 最小匹配类型

f/F float

l/L long double

bool字面值

false true

指针字面值

nullptr

2.2变量

2.2.1变量定义

类型说明符+变量名,变量名…;

例如:

int sum = 0,value,units_sold = 0;

Sales_item item;

std::string book(“0-201-78345-X”);

对象:具有某种数据类型的内存空间,能被程序修改的数据

值:只读数据

初始值

初始化:对象创建时获得了一个特定的值

例如:

double prince = 109.99,discount = price*0.16;

double salePrice = applyDiscount(price,discount);

初始化:不是赋值,创建变量时赋予其一个初始值

赋值:把对象当前值檫除,用一个新的值替代

列表初始化

int units_sold = 0;
int units_sold = {0};
int units_sold{0};
int units_sold(0);
long double ld = 3.1415926536;
int a(ld),b = {ld};//错误,转换未执行,因为存在丢失信息的危险
int c(ld),d = ld;


默认初始化

内置类型的变量未被显示初始化,定义于任何函数体之外被初始化为0

定义在函数体内部不被初始化

类对象没有显示初始化,其值由类确定

std::string empty;`//empty非显式的初始化为一个空串
Sales_item item;   //被默认初始化的Sales_item对象


2.2.2变量声明和定义的关系

声明:使名字被程序所知

定义:创建与名字关联的实体

extern int i;             //声明i并非定义i
int j;                    //声明并定义j
extern double pi = 3.1415;//定义


变量只能被定义一次,但是可以被多次声明

c++是静态类型语言,在编译阶段检查类型(类型检查)

对象类型决定了对象所能参与的运算,在c++语言中编译器负责检查数据类型是否支持要执行的运算,如果不支持,报错并不会生成可执行文件

2.2.3标识符

必须以下划线_或者字母开始

大小写敏感

用户自定义的标识符不能连续出现两个下划线

不能以下划线_紧邻大写字母开头

定义在函数体外的标识符不能以下划线_开头

标识符要体现具体含义

变量用小写字母,例如int index,不要写成int Index或者int INDEX

用户自定义类以大写字母开头,例如:Sales_item

如果标识符有多个单词组成,单词之间要明显区分开来,例如:stdudent_loan或者stdudentLoan,不要写成stdudentloan



2.2.4名字的作用域

作用域

同一个名字在不同作用域中可能指向不同的实体

名字的有效区始于名字的声明语句,以声明语句所在的作用域末端结束

全局作用域

块作用域

在对象第一次被使用的地方附近定义这个对象

嵌套的作用域

内层作用域

外层作用域

#include<iostream>
int reused = 42;
int main()
{
int unique = 0;
std::cout<<reused<<" "<<unique<<std::endl;
//使用全局变量reused;输出42,0
int reused = 0;
std::cout<<reused<<" "<<unique<<std::endl;
//使用局部变量reused;输出0,0
std::cout<<::reused<<" "<<unique<<std::endl;
//显示访问全局变量reused;输出42,0
return 0;
}


如果函数有可能用到某全局变量,则不宜在定义一个同名的局部变量

2.3复合类型

基于其他类型定义的类型

引用和指针

2.3.1引用

为对象起了另一个名字

int ival = 1024;
int &refVal = ival;
//refVal是ival另外一个名字
int &refVal2;
//报错,引用必须被初始化


绑定

引用即别名

为一个已经存在的对象起另外一个名字

引用的定义

int i = 1024,i2 = 2048;
//i和i2都是int
int &r = i,r2 = i2;
//r是一个引用,与i绑定在一起,r2是int
int i3 = 1024,&ri = i3;
//i3是int,ri是一个引用,与i3绑定在一起
int &r3 = i3,&r4 = i2;
//r3和r4都是引用


引用类型要和绑定的对象严格匹配

引用只能绑定在对象上,不能绑定字面值或者某个表达式计算结果

int &refVal4 = 10;
//错误,引用类型的初始值必须是对象
double dval = 3.14;
int &refVal5 = dval;
//错误,引用类型和绑定对象要是同一个类型


2.3.2指针

指向另外一种类型

指针本身就是一个对象,允许对指针赋值和拷贝,在指针生命周期内,它可以先后指向几个不同的对象

指针无需在定义时赋初值,在块作用域内,如果不赋初值,它将拥有一个不确定的值

int *ip1,*ip2;
//ip1,ip2都是指向int型对象的指针
double dp,*dp2;
//dp2是指向double型对象的指针,dp是double型对象


获取对象的地址

int ival = 42;
int *p = &ival;


double dval;
double *pd = &dval;
double *pd2 = pd;
int *pi = pd;
//错误,指针pi类型和pd类型不匹配
pi = &dval;
//错误,试图把double类型对象的地址赋给int


利用指针访问对象

解引用符(操作符*)

int val = 42;
int *p = &val;
cout<<*p;
*p = 0;
cout<<*p;


&和*多重含义

int i = 42;
int &r = i;//引用,r是i的别名
int *p;//声明,p是指针
p = &i;//&取地址
*p = i;//*解引用
int &r2 = *p;//&引用,*解引用


空指针

不指向任何对象

int *p1 = nullptr;//等价于int *p1 = 0;
int *p2 = 0;//直接将p2初始化字面量0
int *p3 = NULL;//要#include <cstdlib>,等价于int *p3 = 0;


NULL预处理变量

int zero = 0;
pi = zero;//错误,不能把int变量直接赋值给指针


初始化所有指针变量为0或者nullptr

赋值和指针

一旦定义了引用,就无法在绑定到另外对象

指针可以指向其他对象

int i = 42;
int *pi = 0;//pi被初始化,但没有指向任何对象
int *pi2 = &i;//pi2被初始化,存有i的地址
int *pi3;//如果pi3定义在块内,则pi3的值无法确定
pi3 = pi2;//pi3和pi2指向了同一个对象i
pi2 = 0;//pi2不指向任何对象


赋值永远是改变等号左边的对象

pi = &val;//pi的值改变了,现在pi指向了ival
*pi = 0;//val的值被改变了,指针pi并没有改变,指针pi指向的对象发生改变了


其他指针操作

int ival = 1024;
int *pi = 0;
int pi2 = &ival;
if(pi)//pi的值是0,因此条件是false
//
if(pi2)//pi2指向ival,因此条件是true
//


任何非0指针对应的条件值都是true

==与!=

他们都为空

指向同一对象

指向一个对象,指向另一对象的下一地址

void*指针

可以存放任意对象的地址

double obj = 3.14,*pd = &obj;
void *pv = &obj;//obj可以是任意类型的对象
pv = pd;//pv可以存放任意类型的指针


拿它和别的指针作比较

作为函数的输入或者输出

赋值给另一个void*

不能直接操作void*指针所指对象

2.3.3理解复合类型的声明

int i = 1024,*p = &i,&r = i;
//i是int型数,p是一个int型指针,r是一个int型引用


定义多个变量

指向指针的指针

int ival = 1024;
int *pi = &ival;//pi指向一个int型数
int **ppi = π//ppi指向一个int型指针


指向指针的引用

int i = 42;
int *p;
int *&r = p;//r是一个对指针p的引用
r = &i;//r引用了一个指针,因此给r赋值&i就是令p指向i
*r = 0; //解应用r得到i,也就是p指向的对象,将i的值改为0


从右往左读取和理解变量

2.4const限定符

const int bufsize = 512;


2.4.1const的引用

2.4.2指针合const

2.4.3顶层const

2.4.4constexper和常量表达式

2.5处理类型

2.5.1类型别名

2.5.2auto类型说明符

2.5.3decltype类型指示符

2.6自定义数据类型

2.6.1定义Sales_data类型

2.6.2使用Sales_data类

2.6.3编写自己的头文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: