C++ 基础(一)

C++定义包括算数类型和空类型在内的基本数据类型。算数类型包含整型数(字符、整型数、布尔值)和浮点数;空类型不对应特定具体的值,仅仅用于一些特殊场合。

1. 数据的类型

其中,字符类型(char)的大小一般与一个机器字节相同为 8 位,而其他整型数的大小与机器相关。但在C++中有如下基本规定:

sizeof( long long ) >= sizeof( long ) >= sizeof( int )  >= sizeof( short ) 
而对于浮点数来说,float一般是一个字表示(7位有效位),double以两个字表示(16位有效位).

除布尔类型和扩展的字符类型外,其他整型刻划分为带符号的和不带符号,一般在类型前面加上unsigned即可。


2. 类型的转换

举例说明一些简单的类型转换

int a = 150; 

float f = 2.1;

bool b;

b = (a != 0)? true: false;  // b = true

a = (b == true)? 1:0;       // a = 1

a = f;    // a = 2

unsigned char c = -1  // c = ( -1 % 256 ) = 255

当一个算术表达式中既有无符号数又有int值时,那个int值就会被转化为无符号数;当无符号数减去一个值时,不管这个值是不是无符号数,其结果必须非负。

for ( unsigned u = 10; u >= 0; --u)
	std::cout << u << std::endl;
以上程序表面上看会输出10 - 0,但实际上却意味着死循环。


3.字面值常量

整型的字面值常量有三类形式表示: 十进制、0开头的八进制、0x开头的十六进制。 尽管整型字面值可以存储在带符号数据类型中,但实际上十进制字面值不会为负数,仅仅表示对其值取负;

字符常量:单引号引的单个字符;

字符串常量:双引号引起的多个字符常量,其实质是由常量字符构成的数组,编译器会在其末尾加入“\0" 。

有两类字符不能直接使用:一类是不可打印字符,另一类是转义序列(以反斜线开始),其泛化形式包括 "  \xff "(x加16进制数) 或” \123 " (8进制数)。若采用八进制的方式,反斜线后跟着多个数字则只有前面3个构成转义。

布尔类型的字符常量为true 和false。


4. 变量

变量 or 对象这两个概念指一块能存储数据并具有某种类型的内存空间。

变量的显式初始化方式:

int unit = 0;

int unit(0);

int unit{0} ;

int unit = {0};
使用花括号初始化称为列表初始化,仅在C++11中有全面的应用,当该初始化存在数据丢失的危险时,编译器将报错.


若变量未显式初始化,则变量被“默认初始化”:

对于内置类型:定义在任何函数之外的内置类型变量,被初始化为0 ; 定义在函数体内部的内置变量不被初始化,其值未定义.

类的对象:若类的对象没有显式的初始化,则其值由类确定.


5. 声明和定义的关系

C++ 区分声明和定义的目的主要是为支持分离式编译。

声明和定义的区别在于定义除规定变量的类型和名字还会申请存储空间,并赋予变量初始值.

如果想声明一个变量而非定义它,可以在变量名前添加关键字extern,而且不要显式的初始化变量,因为"任何包含了显式初始化的声明即成为了定义.

extern int i;//声明
extern int i = 0 ; //定义
int j;    //定义

在函数体内部,如果试图初始化一个由extern标记的变量将引发错误.


6. 变量的命名规则

C++中的标志符由字母、下划线和数字组成,其中必须以字母或下划线开头,无长度限制但大小写敏感。需要注意以下问题:a.不能出现连续两个下划线; b. 不能以下划线紧连大写字母开头 ; c.定义在函数体外的标志符不能以下划线开头。


7. 变量的作用域

C++中大多数作用域都以花括号分隔,一般在第一次使用变量时定义它。


8.复合类型

复合类型指基于其他类型定义的类型,如引用和指针。


引用:

引用必须初始化,且无法重新绑定(即不能变更引用的对象),其本身不是一个对象,因此不能定义引用的引用,它不能与字面值或者表达式的值绑定在一起。

指针:

指针本身是一个对象,且无须初始化,但和内置类型一样,若在块作用域内定义个一个未初始化指针,其将有一个不确定的值(野指针)。


指向指针的引用:

int i= 0;
int *p;
int * &r =p;
r = &i;
*r = 1;


空指针:

即null pointer不指向任何对象,以下是创建空指针的方式

int *ptr = 0;
int *ptr = NULL;//NULL是一个预处理变量,其定义在cstdlib文件中,其值为0

int *ptr = nullptr;//C++11
尽管可以再初始化指针时使用0,但绝不可以将int变量直接赋值给指针。指针的比较运算,一般是对比的两个指针的值。

定义指针时,最好使用下面的方式:

int *ptr = NULL;

当想要在同一行定义多个变量时,该方式较为容易理解,如果写成下面的形式,非常容易让人误会ptr2也是一个整型指针而非变量:

int* ptr1,ptr2;

9.const 限定符号

由于const对象一旦创建其值就不能再改变,所以const对象必须初始化:

const int i = getsize();
const int j = 28;
一般来说,const限定符仅仅在需要改变对象的值时才有意义,其他时候均与普通变量的使用方法一致。默认情况下,const对象被设定为仅在文件内有效,当多个文件中出现同名const变量的时候,其实等同于在不同文件中定义了独立的变量。实际上,编译器会在编译过程中将const对象替换为对应的值。

但是,如果我们需要在不同文件中使用同一个const变量,我们可以通过在const变量前加extern关键字(定义和声明都要加),这样我们该常量就可以被其他文件 使用了。


对于const的引用,我们应如下定义:

const int ci = 1024;
const int &r = ci;
与普通引用不同,对常量的引用不能被用作修改它所绑定的对象,且常量引用在初始化时右式可以是任意表达式、非常量对象,字面值甚至一般表达式。对const对象的引用,仅表明是用该引用无法更改对象的值,对象的值仍可以通过其他方式更改。


指向常量的指针:

const double pi = 3.14;
const double *ptr = &pi
double *ptr2 = pi; //错误的,指向常量的指针与其指向的对象类型需要相同

顶层const表明对象(指针) 本身是一个常量,而底层const表示对象(指针)所指的对象是一个常量。在执行对象拷贝时,顶层常量基本不受影响,而底层常量具有较多的限制。


10. 处理类型

类型别名的定义方式:

typedef double alias;//为double类型定义一个别名alias
如果别名纸袋的是复合类型或者常量,那么在声明语句中就会产生一些意想不到的后果:

typedef char *pstring;
const pstring cstr = 0;//cstr为指向char的常量指针而非指向const char的指针

11.预处理器

预处理器为一段在C++编译工作执行前的运行的程序,如我们常用#include功能即在编译时将#include标记的文件内容替代标记,还有一种常用的预处理功能是头文件保护符,其依赖于预处理变量:

#ifndef XXX
#define XXX

// Your code here

#endif
相关文章
相关标签/搜索