C++编程思想学习—C++中的C特征

1、数据类型

C++标准只规定每种数据类型的最大值、最小值。至于用二进制编码表示,还是以BCD码表示并未规定,所以,对于不同的编译器,不同的造作系统(如:32位的以及64位的操作系统),每种数据类型所占用的字节数不一定相同。

Float为单精度浮点数,double为双精度浮点数。说明符用于修改数据类型具有的最大值、最小值。说明符有shortlong, signed, unsigned

2、指针的作用

      设计指针时的一个很大动机就是在函数内部通过指针改变外部对象。在C++中除了指针又引进了一种新的对于地址的使用方式,即为引用。引用为对固定地址的传递,可以认为具有常量指针的某些特征—不能改变所指向的地址。使用引用使得对地址的传递更加方便。

      指针的类型中的Void类型的使用比较特殊。Void类型的指针允许指向任何类型的数据类型。所以,在使用之前(即存取指向的地址位置的内容之前)必须对其进行强制的类型转换,增强了程序的灵活性。但是,Void类型的指针还是不提倡使用。因为,它可以将一种类型转化为另一种类型,所以,可能带来程序的奔溃。

3、变量的作用域

      变量的作用域为从变量定义起始行到与定义该变量前一个最近一个开括号配对的第一个闭括号。

4、静态变量

      静态变量同全局变量有一定的相似之处,他们都存在于整个生命周期,而不像局部变量只是在进入作用域时自动生成,离开作用域时自动消失。所以,同样可以用静态变量记录一些函数调用之间的片段信息。静态变量只在第一次调用时执行,函数调用之间变量的值保持不变。但是,静态变量的作用域范围则与全局变量不同,静态变量在其范围之外是不可用的,所以,可以使它不被外部的程序所破坏。当静态变量用于所有函数名和所有函数外部的变量时,它会将作用域限定在此文件范围以内。由于静态变量的作用域最多为文件域,所以,它不能与外部变量extern同时用于描述某一变量的特性。

5、外部变量

      用于使用外部文件的一个变量,当在一个文件中看到extern的外部变量时,编译器即知道,在别的某个文件中或者本文件的后面存在在这样的一个变量的定义。

6、连接

      有内部连接和外部连接。内部连接只对正在编译的的文件创建单独存储空间。用内部连接,别的文件可以使用相同的标识符或者全局变量,连接器不会发生冲突。

      外部连接为所有编译过的文件建立一个单独的存储空间。通过用关键字extern声明,可以从别的文件访问此变量和函数。C++中默认将函数和全局变量定义为外部连接。

这里先介绍一下自由函数:如果一个函数为自由函数,那么该函数即不是类的成员函数也不是友元函数。

C++中有内部连接情况如下:

      命名空间中的静态变量、静态自由函数、静态友元函数、常量的定义

       Enum定义

       Inline函数定义

      声明

      类的定义(同时,类的成员函数、变量在类的内部的声明永远都有内部连接)

      Union的定义

      友元函数为全局作用域,但是为内部连接属性。

C++中有外部连接的情况如下:

             命名空间中的非静态变量、非静态自由函数、非友元函数

             类中的静态成员变量

             类的非inline成员函数的定义(即成员函数不是在类的内部定义,是在将成员函数的定义域声明分开)全都为外部连接

             Main()为全局自由函数为外部连接,所以,不能有两个main()函数

内联函数总有内部连接。所以,类的内联成员函数的定义,最好放在定义本类的头文件中。若放到别的文件中在连接的时候就会产生找不到外部连接的错误。

7、常量

      C++中可以使用const来定义某一个对象为常量,这一点与C是相同的。但是,他的作用域与C中的确大大不同。C++中如果用const定义某对象除了限制该对象不能被改变之外同普通变量一样有着自己对应的作用域。但是,C中却不是,在C中会为const创建存储空间,所以,如果在多个文件中定义相同名字的const常量则编译器将会报错0。在C++中一般将const定义放在头文件中,这样当有文件对它使用时,该文件只要包含此头文件。从而将const常量引入此文件,而此时编译器并不const常量分配存储空间。如果,一个常量被别的文件显式的用extern关键字所引用时,为了能被多个文件所使用,此时编译器必须要为常量分配空间,但是,一旦为此常量分配空间就意味着编译器此时不能知道此常量的值了(此时值存放在内存中),所以,也就不能使用常量折叠了。

      由于const不能完全避免内存分配,所以,const默认为内部连接,从而将const常量域限制在文件内,这样避免被多个文件所引用,而致使在多个文件中分配内存,造成重复的分配内存。这样文件域中的const变量就可以在文件中用常量折叠。即使在单文件中const常量被迫分配了存储空间,但是由于const为内部连接属性,编译器知道常量值被保存到程序的某个地方,也知道const常量的值是不会改变的,所以,常量的值仍然是有效的,所以,仍然可以在此文件域中使用常量表达式以及常量折叠。

      常量折叠:即编译时已经获得了这个变量的值(常量),这样就可以用这个常量去定义一些数组的大小等。如:int a[MAX];MAX为一个常量。

8、预处理宏

      宏可以方便程序参数的修改,节省输入时间。所调宏的地方预处理器都将用宏的定义所替换。但是,使用宏也有一定的风险——C++编译器对所有使用宏的地方不进行数据类型的检查。

9、运算符

      位运算符,处理一个数中的个别位(因为浮点数采用一种特殊的内部格式,所以,运算符只适用于整型char int long)。

      移位运算符,右移为<<,左移>>。移位时要注意是逻辑移位还是算数移位。

9C++中的数据类型的转换

      对一般的对象进行类型转换不会出现问题。但是对指针的类型的转化要特别的小心,如将指向一个占用存储空间小的变量转化为一个比他大的存储空间时,可能会破坏别的数据。

显式的类型转化:static_cast,用于良性、适度良性转换。包括编译器允许的做的,不用强制转换的“安全转换”以及不太安全但是清楚定义的变换。Const_cast用于对constvolatile的转换。Reinterpret_cast,就是当用的时候却发现,所得到的东西已经不同了,以至于他不能被用于类型原来的目的,除非把他转换回来,这个是最不安全的转换机制。

10asm关键字、typedef关键字、struct关键字、枚举

       Asm关键字用于在C++中嵌入汇编语言,用于高校调整以及特殊的处理器命令。Typedef,类型别名,用于节省输入,但大量使用会导致程序的可读性变差。Struct将基本的数据类型组合成复杂的数据类型。C++中的struct创建结构体时默认已经加入了typedef。所以,可以将struct所定义的数据结构当做基本的数据类型一样使用。结构体变量、以及结构体数组的使用和一般数据类型的变量和数组的使用方式相同,地址的取地址的方式也相同。&Stru取一个结构体变量的地址。&str[i]去一个结构体数组对象中某一个的地址。

      枚举,即是将标识符与一整数联系起来,方便程序的阅读,但是由于存在不安全的类型转换。所以,在C++中很少使用。

11union

      使用联合的目的是减少内存的浪费,可以用一个变量来存放不同的数据类型,而联合的大小为联合中最大的数据类型的大小。在联合中存放数据时都是存储在联合的起始位置。所以,同一时间联合只能存放一个数据。

12C++中的程序运行时的命令行参数

       Int main(int argc , char * argv[]),其中argc用于记录命令行参数传递过来多少个参数,默认会将本程序的名字和路径放到第一个参数的位置,即argv[0]处。

      此处提一下,在标准的C库的<cstdilib>中提供了atoi(),atol以及atof()。可以方便的将ASCII码很方便的转化为int,long,double浮点值。宏定义时,可以用“#参数”预处理命令将这参数转化为一个字符串。

13、指针的算数运算

      指针会根据所指向的数据类型而动态的选择相应算术运算的基本单位。如intdoublefloat等。但是,两个指针的相加是没有意义的,编译器也不允许这样干。

14C++中的main()函数的参数

       Main函数有两个参数,int main(int agrc , char * argv[])第一个参数agrc为后面参数数组的大小。第二个参数中存放着由命令行输入的参数,默认数组的0号下标存放此执行程序的路径及名称。

15、调试技巧

调试标记,可以使用#define定义一个或者多个标记。根据这些标记可以测试一个使用

#ifdef

code

#endif

所限定的测试代码(code)。

       Assertargumnet)宏,也可以在代码中使用该宏来测试程序运行到本assert()时是否正常(argument(断言)是否预料的值)。如果正常则继续运行,否则发出一个错误消息,并告诉断言是什么以及失败之后将停止程序的运行。使用assert()断言需要包含C++语言cassert标准头文件。调试完成后在程序的#include<cassert>之前插入#define NDEBUG,就可以消除红产生的代码。

16、函数地址

函数在载入计算机时会占用一定的地址,所以,函数也有地址,也可以定义一个函数指针来指向某一个函数。如:void (*funcPtr)();为定义了一个指向无返回值,无参数的函数指针。定义函数指针时采用“从中间开始,向两边扩张,先右后左”的原则。如:

void *(*(*fp1)(int))[10]

表示为:fp1是什么——fp1是一个函数(右)——fp1是一个指向函数的指针(该函数有个int型的参数)(左)——fp1是一个指向函数的指针(该函数有个int型的参数)。该函数返回一个数组,数组的大小为10(右)——fp1是一个指向函数的指针。该函数返回一个指针数组,指针数组中的指针的类型为void类型,指针数组的大小为10。(左)。再如,

int (*(*f4())[10])()

为定义一个函数:f4是一个指向函数的指针,该函数返回一个大小为10的指针数组,指针数组中的指针指向一个函数,该函数返回一个int型值。如同数组的名字代表数组名字指向数组的地址一样,函数的名字也指向函数的地址。

17、指针常量和常量指针

      指针常量:指针是一个变量,所以,它可以指向不同的常量,但是它指向的是一个常量,即它指向的地址不能存放别的值。

      常量指针:指针是一个常量,它只能指向一个地址。而该地址是一个变量可以存放不同的值。

      用法:常量指针:const * ptr,指针常量:* const prt

18volatie关键字

      volatile关键字告诉编译器,这个变量是一个特殊地址。这个地址的内容可能被某些编译器未知的因素所修改。如:操作系统,多线程,汇编代码、硬件所改变。所以,告诉编译器不要优化该变量(每次对该变量的访问都从改变所在的地址访问,而非优化过的寄存器等)。来保持数据的一致性、有效性。

 

       此文为个人学习C++编程思想时个人心得体会,所以,难免有不严谨之处,甚至有可能是错误的理解。如发现错误,或者疑问。欢迎提出讨论,共同学习、进步

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值