C++ Primer Plus 自学笔记2:函数及数据类型简介

函数简介

函数原型及函数头

#include 
using namespace std;

double square(double i);

int main(){
    cout<

main函数前面这行,就是square的函数原型。所谓的函数原型,就相当于变量声明之于变量,是对函数的一种声明。如果函数原型的这条语句没有末尾的分号,编译器就会把这一行识别为函数头(相当于上述代码中的第10行),并要求接下来提供实现该函数的函数体(11~12行)。

一般用户的自定义函数按以上写法来写,先在main函数前进行声明,再在main函数后对函数进行定义(多说一句,函数的定义不能嵌套在任意函数之中,每个函数的定义都是独立、平等的)。当然也可以省略函数的声明,直接在main函数前对函数进行完整定义,但格式上感觉不太美观……

函数原型可在代码中直接进行声明,也可以在代码include的头文件中进行声明。一般头文件中仅提供函数原型,函数的真正实现可能在其他文件中(例如头文件对应的库文件)。

 

整型

分类

C++中的整型有char、short、int、long、long long五种类型(全名分别为short int、long int、long long int,但一般都简写……),每种类型都有有符号版本和无符号版本,因此总共有10种整型。

char也有无符号型,也就是说char可以放一个负数。按之前的理解,char为字符型,实际上在陨石时char被作为整数进行处理,只有在输入输出时,通过cin、cout的处理,可与字符相转换。

为了适应日益繁多的字符类型,C++ 还推出wchar_t 类型,C++ 11 标准还加入了char16_t 和 char 32_t 类型。

范围

#include 

通过以上头文件可使用几个系统自带的常量,这些常量也清晰地界定了各数据类型的数据范围(Win10 64位环境下):

//char类型占8位,无符号型为0~255
CHAR_MIN = -128
CHAR_MAX = 127

//short类型占16位,无符号型为0~65535
SHRT_MIN = -32768
SHRT_MAX = 32767

//int类型占32位,无符号型为0~2^32-1
INT_MIN = -2147483648
INT_MAX = 2147483647

//long类型占32位,无符号型为0~2^32-1
LONG_MIN = -2147483648
LONG_MAX = 2147483647

//long long类型占64位,无符号型为0~2^64-1
LONG_LONG_MIN = -9223372036854775808
LONG_LONG_MAX = 9223372036854775807

比较有意思的是,如果超过了数据范围上限,则变量值会为最小值,同理,低于下限会变成最大值,即INT_MAX + 1 = INT_MIN,INT_MIN -1 = INT_MAX,无符号型同样有该特性。

按ISO/IEC 14882:2011(即C++ 11标准),无符号类型的char、short、int、long、long long的数据范围都不得低于排在它前面的哪一种数据类型,且标准提到了,具体数据范围可根据环境制定。其中,int型应该为“自然长度”,也就是计算机处理起来效率最高的长度,例如在32位系统中,int就占32位,但在16位系统中,int一般只能占16位。当然也有例外,windows64位环境下,int仍然只占32位。

因此同样的数据类型,在不同系统内其数据范围可能不同,需要注意。

C++ Primer Plus 自学笔记2:函数及数据类型简介_第1张图片

整型字面值

除了十进制,C++支持用八进制和十六进制表示整数。

八进制:第一位为0,第二位为0到7的数字,则从第二位开始到结束的一整串数字表示一个八进制整数,如012,表示的数字十进制下为11。

十六进制:第一位为0,第二位为“x”或“X”,则从第三位开始到结束的一整串数字表示一个十六进制整数(A~F大小写均可)。如0xF,表示十进制数15。

无论用何种表示方法,在cout的时候统一转换成十进制表示。当然也可用格式控制符指定显示以何种进制显示:

int a = 0xf;
cout<

常数后缀

数字常量后可用字母后缀定义其类型,其中,对于整数来说,“u”表示无符号,“l”表示long类型,“ll”表示ll类型。其中,这些后缀顺序随意,大小写不影响,举一些例子:

65536ull
65536llu
999l
999u

然而,常数后缀有什么用呢,目前据我所知有以下用途:

1. 使用auto进行类型推导时(相关知识以后会提到)

2. 隐式转换。C++中对于整数数字的处理,如果在int范围内就处理为int型,超出则根据平台情况处理为long或long long类型,在用整数数字进行运算时,一般int与int运算,结果默认也为int型,则就会有以下情况产生:

long long b = 2100000000 * 2;

系统会报错,虽然相乘的结果没有超出long long范围,但两个乘数默认处理为int型,相乘结果也默认为int型,则就超了。正确写法:

long long b = 2100000000ll * 2;

另外,这套后缀体系可以和八进制、十六进制混用:

long long a = 0x7D2B7500ll * 010;

 

浮点型

分类

分为float(单精度)、double(双精度)、long double三种类型,分别为32、64、128位。(和整型数据类型一样,这三种浮点型实际大小也不是全平台固定的,以上结果为Win10系统下所得)

范围及存储方式

浮点数的存储以2为底数的科学计数法表示,即 a × 2^k 这种形式,且a、2、k均以二进制形式存储。

以float为例,float 的32位按如下方式使用:1位存储符号,23位存储尾数(即a),8位存储指数(即k)。

指数存储:指数存储的值减去127,才是实际的指数值。举个例子,‭01011011‬转换成十进制为133,其对应的实际指数值就是133-127=6。此外,指数11111111用于表示特殊情况,指数全为1,尾数全为0,用于表示无穷,指数全为1,尾数不为0,用于表示NaN。因此,指数表示范围为-127到127。对应十进制,就是10^(-38) 到 10^38的范围。

尾数存储:实际上,23位的长度可以表示24位尾数,这是因为写成科学计数法后,a的第一位永远是1,例如1. 010011...因此尾数的第一位就被省略掉了。

因此,float所能表示的最大的数(除了符号位全为1)转换为十进制是:1.11111…(小数点后23个1) × 2^127

\large = (1+\frac{1}{2}+\frac{1}{4}+...+\frac{1}{2^{23}})* 2^{127}

\large = (2^{23}+2^{22}+... + 2^{0})* 2^{-23}*2^{127}

\large = (2^{24}-1)* 2^{127-23}

\large \approx 3.4028*10^{38}

double类型为1位符号,11位指数,52位尾数。

有效位数

对于float,十进制下有效数字有7位,举个例子:

float a = 3.000001;
float b = 3;
cout<

前者输出9.53674e-007,后者输出0,这是由于float 的精度只能达到小数点后6位(也就是7位有效数字),因此有效数字的第八位会被四舍五入掉(区别:如果将小数赋值给整型,小数部分会被直接舍掉,而不是四舍五入)

double则可以达到15有效数字的精度。

浮点型常数表示

可以采用类似科学计数法的方式表示浮点型常数:例如,38.675,可表示为:3.8675e+1,e(E也可以,大小写不限)后面是10的指数,其中指数为正的话加号可以省略。

另外,可以指定浮点型常数的类型。默认情况下为double型,“f”后缀表示float型,“l”后缀为long double型,大小写不限,且可以和上述的科学计数表示法混用。

cout<< 3.0000001f - 3;
cout<< 3.0000001 - 3;

前者输出0,后者输出1e-007,这是因为3.0000001被指定为float型后,由于只能保证7位有效数字的精度,最后的1就被舍掉了。

 

对数据类型的操作

变量命名

变量名由下划线、字母、数字组合而成,其中不可用数字作为开头。单个下划线可作变量名。

下划线打头的变量是合法的,但不建议用户自定义变量采取这种命名方式。因为“_”、“__”开头的多为系统库函数和宏的名称。如果用户非要这么用,也是可以的,但不能保证运行的稳定性。

列表初始化(List-initialization)

函数内的变量创建而不初始化,其值一般为变量创建前对应内存空间中的值。

列表初始化方式:

int a = {5}

将a初始化为5,其中,“=”可以省略,如果初始化为0,大括号内可以什么都不填。

该初始化方法适用于几乎全部C++自带数据类型

char c{};
string s{"123"};

此外,使用列表初始化,对于变量类型要求更为严格:不允许缩窄(narrowing),即变量的类型可能无法表示赋给它的值。如:

char a {99999};
char b = 99999;

对b的初始化只是warning,但对于a的初始化就是error了……

此外还有:

int a = 70;
char b {a};

运行的时候虽然只是警告,但也需要注意,在初始化b时,由于a是int型,因此很有可能a中的值会超过b的范围。但相反,给一个int型的变量初始化为一个short型变量的值是被允许的。

转义字符

C++ Primer Plus 自学笔记2:函数及数据类型简介_第2张图片

在支持ASCII编码的环境中,“\”后面接应字符对应的八进制或十六进制ASCII码均可转义,以换行符为例,输入 '\xa' 和 '\012' 均可,十六进制前面的零要省去。

虽然以上方式均支持,但建议还是直接使用'\n'这种形式,简单方便不说,在字符串成串操作的时候不容易与后面的字符搞混。

类型转换

当表达式中含有多个不同的数据类型时,会进行整型提升(integral promotion),bool、char、short及其对应无符号型会被统一转换为int型(bool中的true被转换为1,false被转换为0)。但如果表达式中含有long long类型,则不会作进一步提升。(因此最后运算结果如果超出int范围,即使赋值给long long 型,也会出错)

但如果表达式中涉及到浮点型,则会进一步提升到浮点型,并以最大的类型为准进行提升。举个例子(a的赋值会出错而b不会):

long long a = 2 * 2100000000;
long long b = 2.0 * 2100000000;

强制类型转换:(类型名)变量名或常量,类型名(变量名或常量),举个例子:

float a = 1.8;
cout<<(int)9.8;
cout<

输出9,9,1,1。

auto声明

一种特殊数据类型,可以根据变量所赋初始值推断变量类型,如:

auto a = 0;
auto b = 0.0;

a被推断为int型,b被推断为double型。

可以通过sizeof(变量名)来获得变量所占用的内存空间,单位为字节。

cout<

输出为4和8。

 

你可能感兴趣的:(Language)