[C++Primer] 第二章 变量和基本类型

2.1 基本内置类型

  • C++定义了一套包括算术类型 (arithmeric type) 和空类型 (void) 在内的基本数据类型。其中算术类型包含了字符、
    整型数、 布尔值和浮点数。空类型不对应具体的值,仅用于一些特殊的场合,例如最常见的是,当函数不返回任何值时使用空类型作为返回类型

2.1.1 算数类型

  • 算术类型分为两类:整型 (integral type,包括字符和布尔类型在内)和浮点型

    C++算数类型

  • 类型 int、short、long 和 long long 都是带符号的,通过在这些类型名前添加 unsigned 就可以得到无符号类型,例如 unsigned long。类型 unsigned int 可以缩写为 unsigned
  • 类型 char 和类型 signed char 并不一样

2.1.2 类型转换

#include <iostream>
int main(){
    unsigned u = 10, u2 = 42;
    std::cout << u2 - u << std::endl;
    std::cout << u - u2 << std::endl;
    int i=10, i2= 42;
    std::cout << i2 -i<< std::endl;
    std::cout << i - i2<< std::endl;
    std::cout << i - u<< std::endl;
    std::cout << u - i<< std::endl;
    return 0;
}

2.1.3 字面值常量

一个形如42的值被称作字面值常量(literal)

整型和浮点型字面值
20 /* 十进制 */ 024 /* 八进制 */ 0x14 /* 十六进制 */

浮点数

3.14159 3.14159E0 0. 0e0 .001
字符和字符串字面值
// 分多行书写的字符串字面值
std::cout << "a rea11y, rea11y long string litera1 "
             "that spans two 1ines" << std::end1;
转义序列
换行符     \n  横向制表符   \t  报警(响铃)符 \a
纵向制表符   \v  退格符     \b  双引号         \"
反斜线     \\  问号          \?  单引号         \'
回车符     \r  进纸符     \f

2.2 变量

变量提供一个具名的、可供程序操作的存储空间。C++中的每个变量都有其数据类型,数据类型决定着变量所占内存空间的大小和布局方式、该空间能存储的值的范围,以及变量能参与的运算。对C++程序员来说,”变量 (variable)” 和 “对象 (object)” 一般可以互换使用。

2.2.1 变量定义

变量定义的基本形式是:首先是类型说明符(type specifier),随后紧跟由一个或多个变量名组成的列表,其中变量名以逗号分隔,最后以分号结束。

初始值

2.2.2 变量声明和定义的关系

  • 分离式编译 (separate compilation) 机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。
  • 声明extern和定义

2.2.3 标识符

  • 变量命名规范
    变量命名有许多约定俗成的规范, 下面的这些规范能有效提高程序的可读性:
    • 标识符要能体现实际含义。
    • 变量名一般用小写字母, 如index, 不要使用Index或INDEX。
    • 用户自定义的类名一般以大写字母开头, 如 Sales_item。
    • 如果标识符由多个单词组成, 则单同间应有明显区分, 如 student_loan 或studentLoan, 不要使用 studentloano

2.2.4 名字的作用域

嵌套的作用域
#include <iostream>
int reused = 42;
int main(){
    int unique = 0;
    std::cout << reused <<" "<< unique << std::endl;
    int reused = 0;
    std::cout<<reused<<" "<<unique <<std::endl;
    std::cout << ::reused <<" "<<unique <<std::endl;
    return 0;
}
#include <iostream>
int main(){
    int i = 100, sum = 0;
    for(int i = 0;i != 10; ++i)
        sum += i;
    std::cout << i << " " << sum << std::endl;
    return 0;
}

2.3 复合类型

2.3.1 引用

  • 引用 (reference) 为对象起了另外一个名字,引用类型引用 (refers to)另外一种类型。通过将声明符写成 &d 的形式来定义引用类型,其中 d 是声明的变量名:
int ival = 1024;
int &refVa1 = iva1; // refVa1指向iva1(是iva1的另一个名字)
int &refVa12; // 报错:引用必须被初始化
  • 一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定 (bind) 在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因此引用必须初始化。
#include <iostream>
int main(){
    int i = 1, &r1 = i;
    double d = 0.0, &r2 = d;
    std::cout << i << " " << r1 << " " << d << " " << r2 << " " << &r1 << " " << &r2 << std::endl;
    // T
    r2 = 3.14159;
    std::cout << i << " " << r1 << " " << d << " " << r2 << " " << &r1 << " " << &r2 << std::endl;
    // T
    r2 = r1;
    std::cout << i << " " << r1 << " " << d << " " << r2 << " " << &r1 << " " << &r2 << std::endl;
    // F
    i = r2;
    std::cout << i << " " << r1 << " " << d << " " << r2 << " " << &r1 << " " << &r2 << std::endl;
    // F
    r1 = d;
    std::cout << i << " " << r1 << " " << d << " " << r2 << " " << &r1 << " " << &r2 << std::endl;
    return 0;
}
#include <iostream>
int main(){
    int i = 1, &r1 = i;
    i = 5;
    r1 = 10;
    std::cout << i << " " << r1 << std::endl;
    return 0;
}

2.3.2 指针

  • 指针 (pointer) 是 “指向(point to)” 另外一种类型的复合类型。 与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。

    • 其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。
    • 其二,指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
  • 指针存放某个对象的地址,要获取该地址,需要使用取地址符 (操作符 &)

int ival = 42;
int *p = &iva1; // p存放变量iva1的地址, 或者说p是指向交量ival的指针
double dval;
// 正确 : 初始位是 double 型对象的地址
double *pd = &dval;
// 正确 : 初始位是指向 double 对象的指针
double *pd2 = pd;
int *pi = pd;
// 错误: 指针pJ.的类型和pd的类型不匹配
pi = &dval;
// 错误: 试图把double型对象的地址赋给int型指针
  • 如果指针指向了一个对象,则允许使用解引用符 (操作符 * 来访问该对象:
int ival = 42;
int *p = &ival; // p存放着变量ival的地址。或者说p是指向交量ival的指针
cout << *p; // 由符号*得到指针p指的对象,输出42
  • 对指针解引用会得出所指的对象,因此如果给解引用的结果赋值,实际上也就是给指针所指的对象赋值:
*p = 0; // 由符号*得到指针p所指的对象, 即可经由p为交量ival赋值
cout<<*p; // 出0

int &r = i;
int *p;
p = &i;
*p = i;
int &r2 = *p
// &是声明的一部分, *是一个解引用符
int i = 42;
int &r = i; // r 是引用
int *p; // p 是指针
p = &i; // & 取地址符
*p = i; // * 解引用符
int &r2 = *p; // * 解引用符
  • 空指针
int *p1 = nullptr; // 等价于 int *p1 = 0;
int *p2 = 0; // 直接将p2初始化为字面常数0 
// 需要首先#include cstdlib
int *p3 = NULL; // 等价于int*p3 = 0;

2.4 const 限定符

2.5 处理类型

类型别名 (type alias) 是一个名字,它是某种类型的同义词。使用类型别名有很多好处,它让复杂的类型名字变得简单明了、 易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的。

typedef double wages; //wages 是 double 的同义词
using SI = Sales_item; // SI是Sales_item的同义词

2.6 自定义数据结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值