C语言笔记

发布 2021-05-12 01:07:28 阅读 5087

c++ primer读书笔记。

注:本文**。

整理说明:本资料是我在网上无意间找到的,读起来感觉不错,但由于原文是每章一个网页的格式,读起来不是很习惯,而且也不方便保存,所以我花了2个多小时的时间将所有网页的内容综合整理了一下,但最后才发现,文章的顺序颠倒了,所以各位如果愿意阅读本文的话,请从后面向前读,每个红色“标题”代表一章,如有不便还请各位见谅,或到原文**阅览)

标题::类型转换之隐式转换。

对于我们来说,3+1.5=4.5。

但是对于计算机来说,这两个数的相加可不这么简单。因为3与3.0是不同的数据类型,3.

0与1.5是可以相加的,3却不能与1.5相加。

于是,c++在对上面的表达式进行处理时,有必要对其中一个(或两者)进行转换。

因为这个转换是“隐式”的,也就是说这个转换不让程序员知道,那么,系统就不能必须保证不产生损失,这个损失指的是精度。为了不损失精度,数据总是向精度高的类型转换。惟一的例外是当某个变量用作条件时,它被转换为bool型。

对算术类型的转换是这样的:所有比int小的都转为int或unsigned int,即使没有必要也这么转。原因很简单,因为int的长度正好等于字长。

对cpu来说,一次处理一个字是最快的。如果int或unsigned int无法达到要求,则往long、double转化。

如果每一个转换都能不造成损失,那自然是好事。可是世间的事总有不随人愿的时候。对于同一种算术类型,其signed和unsigned所能表达的范围是一样大,但却是互不重叠的两个范围。

就像“妇联”和“工会”一样,往哪边转换都可能会产生损失。这是无法解决的问题,所以,在vc中,试图比较int和unsigned int变量时会显示警告。

奇怪的是,据我测试,在vc++.net中,只有进行“<”和“>”比较的时候才会显示警告,而进行“==和“!=比较的时候却不显示警告。

实际上这两个比较也会有同样的问题产生,比如以下**:

int a = 3;

unsigned b = 4294967293;

if (a ==b) cout <

测试运行以上**会发现表达式a==b的值为true。这是从int转为unsigned int过程中的***,这个***我们应该知道,但是vc++.net不进行任何警告似乎也有些与理不通。

——难道我关闭了某些警告?

其它隐式转换还包括数组名转换为指针、算术值用作条件时转换为bool,枚举被转换为整数,非const对象转换为const对象等。其中枚举转换为整数没什么要提的,枚举值本来就是整数的别名,非const对象转为const对象只是临时声明它的保护级别,通常用于作为参数传递时。

标题::内存管理之new和delete

林锐博士曾将内存管理比喻为“雷区”(《高质量c++/c编程指南》第44页),内存管理这块难不难?恐怕不好说。“会者不难难者不会”嘛。

但是说内存管理这块难以成为“会者”,应该是没有错的。

程序时时刻刻与内存打交道,只不过以往我们不用考虑,甚至不用知道。所以,所谓“内存管理”,是特指堆内存。

如果把堆内存和栈内存的使用放在一起考虑,可以降低对内存管理恐惧。

一、内存的分配:

int i(100);/栈上分配内存。

int *pi = new int(100);/堆上分配内存。

以上两种分配,都使用了100作为初始值进行初始化,如果是进行类对象的分配,它们还可以指定使用哪个构造函数,比如:

cstring s(s1);/栈上分配内存。

cstring *ps = new cstring(s1)//堆上分配内存。

这里的s可以是char*指针,也可以是另一个cstring对象,它的类型将决定上面这两行语句调用哪一个构造函数。

在这里,有一点要特别说明,如果要使用默认构造函数,则new语句后面可以用空括号对,而栈内分配的语句切不可用空括号对。如果写成“cstring s();则并不是定义一个cstring对象s,而是定义一个返回值为cstring的函数s。

上面两种分配,也都可以分配对象数组,不同的是,用new操作符在堆内存分配数组时,只能调用默认构造函数。而在栈上分配却可以指定对象成员的初始值。如:

int a[3] =栈上分配内存,int可以换成其它类型名,后面的初始值可作相应调整。

int *p = new int[3];/不能指定这三个对象的初始值。

二、内存的访问:

栈内存可以通过对象访问,也可以通过指针访问,堆内存通过指针访问。方法完全相同。

三、内存的释放:

栈内存在对象作用域结束后自动释放,堆内存要用delete。

delete pi;//释放内存。

delete p;//释放对象数组。

对于释放对象数组,那个空的对不可以丢,否则将只释放数组的第一个元素。导致内存泄露。

有了以上对比,堆内存似乎没有了任何难度。那么内存管理的玄机究竟在哪儿呢?在进行内存分配与释放的时候,有几个注意点要记住:

1、new操作有可能失败,当系统无法分配需要的内存块时,将返回null值,所以在new操作之后,要立即判断pi的值是否为null。

int *pi = new int(100);

if (pi = null)

2、堆上分配的内存必须delete,而且只可以delete一次。为了保证内存只被delete一次,请务必记住delete以后立即将指针设为null:

delete pi;

pi = null;

虽然“pi=null;”不是必须的,但这是个好习惯。将指针设为null既可以防止继续读写该内存,也可以防止再次释放该内存。

老的c程序员可能忘不了malloc和free函数,它们也可以进行内存的分配与释放。但是c++时代它们已经落伍了。它们只是按请求的字节数进行分配,而不管你用这块内存来干什么。

这样做,就等于放弃了类对象的构造与析构。对于很多类来说,这样做是很危险的。

标题::优先级、结合性和求值顺序。

说到优先级,我能熟练背出“先乘除,后加减”,之于c++列出的整整19个优先级,每个优先级又包含若干个操作符,我总是看了就头皮发麻。以我的记性,连军旗里哪个大哪个小都背不出来,这几十个操作符——还是饶了我吧。

记住林锐博士的话:“如果**行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。”(高质量c++/c编程指南》第26页)这样做最直接的作用是不用记忆了复杂的优先级了,不用记忆并不是因为懒,而是为了更清晰。

毕竟程序不只是编给计算机运行的,当我们处在一个多人协作的团体中时,程序的清晰度和精确性比性能要高得多。再说,多加几对括号是不影响运行效率的。

结合性和求值顺序是容易混淆的两个概念。每一个操作符都规定了结合性,但是只有极少数操作符规定求值顺序。结合性是说如果有多个同级别的操作符,这些操作数该如何分组。

比如“1+2+3”究竟分成“(1+2)+3”还是“1+(2+3)”,虽然这两种分组最终没有区别,但不等于所有操作符都不产生区别。即使不产生区别,计算机毕竟是计算机,它只能按死的规范做事,于其给它灵活机制,还不如规定了结合性让它遵守。

c++只有四个操作符规定了求值顺序,它们是和“,”记住这四个操作符并不难。反过来记住其它操作符也不难,难的是在写程序中是否有这个意识。那么多网友讨论“j = i++ i++ i++;的结果,正说明了还有好多人不了解“未定义”的威力。

如果不小心使用了依赖于未定义求值程序的语句,将是一个不容易发现并改正的问题。比如“if (a[index++]a[index]);

标题::sizeof和逗号操作符。

把sizeof说成操作符可能有些不合习惯,因为sizeof的用法与函数没区别。但是sizeof与函数有着本质的区别:它是编译时常量。

也就是说,在程序编译时,就会求出它的值,并且成为程序中的常量。

sizeof本身比较简单,惟一要提的就是它对数组名和指针进行操作的结果。

int a[10];

sizeof(a);

该操作返回的是数组所有元素在内存中的总长度。但是如果对指针进行操作,返回的则是指针本身的长度,与指针所指类型无关。

正因为数组名与指针有着千丝万缕的关系,所以有时候这个特性会让人摸不着头脑:

int function(int a[10])

sizeof(a);

以上sizeof返回的不是数组所有成员的大小,而是指针的大小,因为数组在参数传递中弱化为指针。

逗号操作符除了在for语句中应用以外,我没发现在哪儿还有用处。因为在一般情况下,逗号改成分号肯定是可以的,在for语句中因为分号的作用另有定义,所以不能随便改。这才有了逗号的用武之地。

标题::条件操作符。

我觉得条件操作符的存在就是为了简化if-else语句。第一,它与if-else语句的功能完全一致;第二,它虽然是一行语句,但是它规定了求解顺序,这个顺序保证了有些表达式不被求值。

条件操作符是有一定的危险性的,危险的原因在于它的优先级特别底,还容易漏掉括号。它的优先级仅仅高于赋值和逗号运算符,也就是说,只有在与赋值或逗号共存时,才可以免去括号,其它情况下都得加上括号。漏加括号的bug是很难发现的。

比如“cout <

标题::箭头操作符(->

箭头操作符是c++发明的全新操作符,但却不是c++才用到的功能。早期的c语言虽然没有类,却有结构体,也允许有指向结构体对象的指针。不同的只是没有发明“->这个符号来进行简化操作。

说到底,“-的出现只是代替原来就可以实现的功能。

引用:c++语言为包含点操作符和解引用操作符的表达式提供了一个同义词:箭头操作符(->

C语言笔记

第一课时。c语言标准格式。include vidomain 以 开头的语句称为预处理指令。include语句不是必须的,但是如果一旦有该语句就必须把它放在文件开始处是standared input output header的缩写standared 标准input 输入output 输出header...

C语言笔记

c语言算法和数据类型。整型。基本类型 字符型注释 基本类型的特点是其不可实型 单精度型以再分解为其他类型双精度型数组型。数据结构 构造型 结构体型共用体型指针型空类型。一 常量。define 语句不以分号结尾,它可以放在源 的任何位置。不过在定义常量时,只有在它定义后的源 中才有效。是一个修饰符,在...

c语言笔记

1.if中别忘了 而不是 2.写完程序别忘了检查前后大括号 小括号是否完全照应。3.遇到几分之几的分数可以方程两边同时乘以一个数来消去分母。4.写指针题时看准指针对应的是行还是列。例 int a 4 3 int p a 0 列指针。int ptr 3 a 行指针。5.考虑好哪些量会随着循环不断改变。...